-
-
Notifications
You must be signed in to change notification settings - Fork 686
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
Use unique_ptr
internally in the implementation of itk::Object
#3620
Use unique_ptr
internally in the implementation of itk::Object
#3620
Conversation
3074254
to
c8376b2
Compare
Any idea what the ITK.macOS.Python failure is about? https://open.cdash.org/viewBuildError.php?buildid=8158841 says:
|
Looking at Azure log:
and then later on
|
I don't know why would git clone from GitHub keep failing. https://github.com/InsightSoftwareConsortium/ITK/blob/v5.3rc04/Utilities/KWStyle/BuildKWStyle.cmake#L25 |
/azp run ITK.macOS.Python |
template <typename TObject> | ||
void | ||
InvokeEventRecursion(const EventObject & event, TObject * self, std::list<Observer *>::reverse_iterator & i); | ||
InvokeEventRecursion(const EventObject & event, TObject * self, ObserverListType::reverse_iterator & i); |
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.
Will this change in the public interface cause backwards compatibility issues?
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.
Good question, thanks @dzenanz but no, I don't see any backwards compatibility issue here. InvokeEventRecursion
is a protected member function of a "hidden" class (ITKCommon_HIDDEN
) named "SubjectImplementation", which is defined inside itkObject.cxx. So InvokeEventRecursion
is also declared and defined in itkObject.cxx, and it isn't being called outside itkObject.cxx. So it's really just an implementation detail. As far as I can see.
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.
I am rather uncertain if the recursive function still works as intended as the list is the sole owner.
@@ -219,7 +208,7 @@ SubjectImplementation::InvokeEventRecursion(const EventObject & | |||
{ | |||
|
|||
// save observer | |||
const Observer * o = *i; | |||
const auto & o = *i; |
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.
I'm not sure what the type is here? Reference to the unique pointer in the list?
The point of this pattern is to save the pointer to the object, in case is deleted/modified. Since the list still has the sole ownership I don't believe this works as intended any more. See the prose above.
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.
Perhaps this should be maintained as a raw pointer, and the below "find" be modified to compare raw pointer of m_Observer items to this save raw pointer?
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.
Is InvokeEventRecursion
exercised in current tests? If not, now would be a good time to cover it by test(s).
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.
There was a reasonable test added for this case: f7307e2 It may be that valgrind will be required to detect the invalid memory access.
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.
[deleted.... I'll be back!]
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.
Perhaps this should be maintained as a raw pointer, and the below "find" be modified to compare raw pointer of m_Observer items to this save raw pointer?
Thanks @blowekamp This comment of yours inspired me to submit pull request #3629: "BUG: Object::InvokeEvent
should not use a dangling Observer pointer"! Please check!
I think this PR (#3620) and PR #3629 can be processed in either order, but it's probably easiest now to first process PR #3629.
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.
With #3629 merged this should be good to go.
Thanks @blowekamp, I'm actually preparing a revision! It appears that because we just abandoned Observer pointer comparison in favor of tag comparison, the list may now simply contain the observers themselves, rather than their pointers! Which further simplifies their memory management! 😃 |
cfeb38d
to
5231f32
Compare
@N-Dekker If you are refactoring the whole thing, the recursive implementation with the search at each level is O(N**2) complexity. We should be able to use a better data structure to reduce the complexity, and improve the efficiency of the is the observer still there. Does the order of the observers are visited matter? Maybe. |
Thanks @blowekamp but my focus is still on trying to avoid manual memory management ( |
I merged #3634. Now this branch has merge conflicts. |
Declared both `m_SubjectImplementation` and `m_MetaDataDictionary` as an `std::unique_ptr`.
The original code technically allowed an `Observer` (from the implementation of `itk::Object`) to be copied, causing its destructor to possibly be called twice, trying to do `delete m_Event` twice on the very same event object. Which would have undefined behavior, possibly causing a crash. This commit solves this potential problem by declaring m_Event as a `unique_ptr`, and removing the user-defined `Observer` destructor (leaving it "implicitly defaulted", following the Rule of Zero). Thereby it also removes the `virtual` keyword from the destructor, which is OK, because `Observer` is not a base class.
Instead of using raw pointers. Also "defaulted" the destructor of `SubjectImplementation`.
5231f32
to
ad87937
Compare
itk::Object
as list ofObserver
objects (instead of a list of raw pointers).m_SubjectImplementation
andm_MetaDataDictionary
as anstd::unique_ptr
.Observer::m_Event
as unique_ptr