-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deprecate Close method in FairSource/Sink #1468
base: dev
Are you sure you want to change the base?
Conversation
a sidenote: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Many thanks for this PR! This is great!
First initial set of comments. I haven't looked deep enough yet.
@@ -558,7 +558,6 @@ void FairRunAna::TerminateRun() | |||
// cout << ">>>------------------------------------------------<<<" << endl; | |||
fRootManager->LastFill(); | |||
fRootManager->Write(); | |||
fRootManager->CloseSink(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sadly enough this is also part of our public API (at least in my view). So we should keep calling the Close
member functions in the deprecation phase. So that people can actually continue using their stuff that depends on their Sink's/Source's Close member function being called.
Maybe we should replace this with something like this at least?
iff(fSink) {
fSink->Close();
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But if we do this, we will always get deprecation warning no matter what. I think deprecation means asking people to fix something to get rid of the warning. But in this case, even they fix it and put the resource closing in the dtor, they still get this deprecation warning because the calling is guaranteed in the library code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The deprecation warning only happens in the FairRoot "library" code while compiling it. So normal users wont be hit by it.
And we should just stop that warning with a set of
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
iff(fSink) {
fSink->Close();
}
#pragma GCC diagnostic pop
Once we finally remove the Close member function, we will get a nice compile error on this, and we can remove all of this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The real problem is, that we can't throw a warning if people override Close. We can't tell them "Well, you have overriden it, so you think that this makes any difference? This behaviour will change!". And I don't know of any good solution to this, except for putting a good warning in the Release Notes (which you did!).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that we can't throw a warning if people override Close.
I think we can't even if we want. If they override the Close method and call it with the derived class type, there won't be any warning. Warning only occurs when they cast back to the base class and call the Close method.
And we should just stop that warning with a set of
I'm not sure whether it's a good idea to still enforce the closing. The point of deprecating the Close method is to tell users to deal with closings themselves. But with this closing, it kind of makes this transition harder. And in some cases where users don't want to close the resources twice, they have to give the controls of closings back to FairRootManager, which is exactly the opposite to what we want. Deprecation means something will be discarded and tell users not to use them. It's weird to see that we deprecate the method while still keep using it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One other note.
PixelDigiBinSource::~PixelDigiBinSource() | ||
{ | ||
fInputFile.close(); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fInputFile
is a std::ifstream. So its dtor should handle that for us. :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More things to keep, IMHO.
Surround them with
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
…
#pragma GCC diagnostic pop
as needed.
void FairRootFileSink::Close() | ||
{ | ||
if (fRootFile) { | ||
fRootFile->Close(); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But I think, this is public API still?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, without the declaration here, FairRootFileSink
still have Close public API, which falls back to the implementation of its base class.
void CloseSink() | ||
{ | ||
if (fSink) { | ||
fSink->Close(); | ||
} | ||
} | ||
[[deprecated("Close will go away, the dtor closes resources")]] void CloseSink() {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please keep the complete old version as well here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could crash user's program if they implement the close in the dtor as well. Some user close implementations may not allow the second closing.
if (fSink) { | ||
fSink->Close(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one should be kept IMHO as well.
GetSource()->Close(); | ||
|
||
fRootManager->CloseSink(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And this one as well.
I have tested FairRoot's private branch without FairSampler::Close() and FairSink::Close() |
Deprecations in GeneralFor me a deprecation means, that
In FairRoot: Public APILet's look at (1): Public API is basically everything in When it comes to FairRoot: The confusing Close situationIn a cool world, the old situation would look like this: class FairSourceSink {
public:
void CloseForUsers() { CloseImpl(); }
private:
// Please override in your implementation
virtual void CloseImpl() = 0;
private:
// So that the library can call private member functions
friend FairRun;
friend FairRootManager;
// Will be called internally by the library as a "call back like thing"
void CloseForInternalUse() { CloseImpl(); }
}; Let's go step by step.
That's my current idea on how this should look like. The problem is now, that all of those three ( To maybe simplify things, we could temporarily invent: private
void CloseForInternalUse() {
// All of these pragmas, because we would call
// CloseImpl (which is not deprecated internally),
// but we have to call Close, which is deprecated
// from (1).
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
Close();
#pragma GCC diagnostic pop
} That's the whole problem here from my point of view. |
Thanks for the replies. Sorry I'm very busy working on other things and don't have time to deal with this PR these days. But probably on this Friday I will read the replies in details and continue to fix the things here if needed. |
Hi, I thought it over again. Yes, the procedures described above is probably the right way to go. But there is still something weird that I couldn't pinpoint what exactly it is in the beginning, especially when I see: private
void CloseForInternalUse() {
// All of these pragmas, because we would call
// CloseImpl (which is not deprecated internally),
// but we have to call Close, which is deprecated
// from (1).
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
Close();
#pragma GCC diagnostic pop
} For me, we are kind of contradicting ourself when we enable a warning from a new deprecation but at the same time we also disable it. I guess the people who designed the "deprecation" in C++ also didn't expect the people to disable it at the same time using a compiler-specific macro (There are some FairRoot users using apple-clang). Our main dispute is whether we should remove the calling of the void CloseSink()
{
if (fSink) {
fSink->Close();
}
} Here are my arguments why it should just be removed based on the following principles:
The point 2 and 3 are supported by C++ guidelines from Herb Sutter about why virtual functions should be private. In this articles, it says
It also implies here that the derived classes which overrides the virtual functions are just customization. For example, if we are designing an abstract class for a person wearing a T-shirt and pants. It's the job of the derived classes (User's classes) to decide what kind of T-shirt and pants are (e.g colors and sizes). But the logic connection between those objects are determined by the abstract class (the library implementer). Users shouldn't be concerned about in which order they are put up or whether they are put up or not. Suppose if we want to let the person wear T-shirt first instead of pants first, we could just change that order without doing any deprecation of the old order. Deprecation is used to notify the users. If it's irrelevant to users, it should not be deprecated but rather simply removed. So now let's get back to |
Checklist: