[IGSTK-Developers] Observer/Observable pattern
Ziv Yaniv
zivy at isis.imac.georgetown.edu
Sun Feb 25 18:42:25 EST 2007
Hi Luis,
Thanks for the reply.
I went over the code you sent and I am wondering why it compiles?
In itk::Object the signatures of AddObserver are:
unsigned long AddObserver(const EventObject & event, Command *);
unsigned long AddObserver(const EventObject & event, Command *) const;
Using a raw pointer to the Command object.
In your code you pass a smart pointer. The code compiles and runs,
so I'm wondering what an I missing here?
thanks
Ziv
---------- Original Message ----------------------------------
From: Luis Ibanez <luis.ibanez at kitware.com>
Date: Sat, 24 Feb 2007 09:11:23 -0500
>
>Hi Ziv,
>
>
> Good point.
>
>
> It seems that there is a mix of terminology here.
>
>
>
>There is the term "Observer" that we usually associate to the
>"itk::Command" class. However, there is also the class "Observer"
>that is explicitly defined in the itkObject.cxx file in lines 31-45.
>
>
>There is the "Observable" term, that we usually associate to the
>"itk::Object" class and its descendants, but there is also the
>itkSubjectImplementation class that is defined in itkObject.cxx
>in lines 49-65.
>
>
>
>Here is the list of relationships:
>
>
>itkObject *has one* pointer to an instance of SubjectImplementation.
> itkObject.h line 181.
>
>itkSubjectImplementation has a list of pointers to Observers
> itkObject.cxx line 63: std::list<Observer* > m_Observers;
>
>itkObserver has a SmartPointer to an itkCommand.
> itkObject.cxx line 42
>
>itkObserver has a raw pointer to an itkEventObject
> itkObject.cxx line 43
>
>
>The "itkObserver" helper class maintains the association between
>an itkCommand and the event that it has declared to be interested
>in listening from.
>
>
>
>The following diagram may help to illustrate these relationships:
>
>
>itkObject -----> itkSubjectImplementation
> |
> |---> itkObserver ---> itkCommand
> |
> |---> itkObserver ---> itkCommand
> |
> |---> itkObserver ---> itkCommand
> |
> |---> itkObserver ---> itkCommand
> |
> |---> itkObserver ---> itkCommand
> |
>
>
>When you call itkObject::AddObserver( event, command ) in line
>389 of itkObject.cxx, the call is delegated to the SubjectImplementation
>AddObserver() method, that is defined in itkObject.cxx lines 80-86.
>In this method, an instance of "itkObserver" is created and initialized
>with the Event and Command, then pushed into the std::list of Observers
>that the SubjectImplementation uses.
>
>The SubjectImplementation class is responsible for the memory of the
>"itkObserver" instances, as you can verify in lines 73, 112 and 127;
>but it is not directly responsible for the memory of the itkCommand
>instances. These last ones are managed simply by the fact that the
>instances of itkObserver had a SmartPointer to them.
>
>
>--
>
>
>That being said, It seems that the documentation is innacurate on
>the aspect of:
>
> " The memory for the Command becomes the responsibility of
> this object, so don't pass the same instance of a command
> to two different objects"
>
>Since with the current strucutre of code there is no reason why
>an instance of an itkCommand couldn't be set as AddObserver()
>of multiple itkObjects.
>
>
>
>
>In any case: to differentiate faith and supersition from Truth,
> there is nothing better than an Experiment.
>
>
>
>So, please find attached a minimal example of source code
>demonstrating that you can use the *same* Command to listen
>to more than one different itkObject, and that if one of the
>objects is destroyed, the itkCommand is still alive.
>
>The program also demonstrate that a single itkCommand can
>listen event from different objects, and differentiate them
>based on the itk::Object caller argument of the Execute()
>method.
>
>
> Please give it a try to this code and let us know
> if you still have any questions.
>
>
> We should probably fix the ambiguous
> documentation of the itkObject class.
>
>
>
> Regards,
>
>
>
> Luis
>
>
>
>
>
>----------------
>Ziv Yaniv wrote:
>> Luis,
>> If what you say is correct then the ITK documentation is wrong.
>> This is from the itkObject.h file:
>>
>> /** Allow people to add/remove/invoke observers (callbacks) to any ITK
>> * object. This is an implementation of the subject/observer design
>> * pattern. An observer is added by specifying an event to respond to
>> * and an itk::Command to execute. It returns an unsigned long tag
>> * which can be used later to remove the event or retrieve the
>> * command. The memory for the Command becomes the responsibility of
>> * this object, so don't pass the same instance of a command to two
>> * different objects */
>>
>> That is where I got my many-to-one understanding.
>>
>> Ziv
>> ---------- Original Message ----------------------------------
>> From: Luis Ibanez <luis.ibanez at kitware.com>
>> Date: Fri, 23 Feb 2007 18:34:56 -0500
>>
>>
>>>Hi Ziv,
>>>
>>>The Observer pattern in ITK was mostly copied from
>>>the functionality existing in VTK at the time.
>>>
>>>The relationship between Observers and Observables
>>>is a many-to-many relationship. That is, and ITK
>>>object may have many Observers connected, and a
>>>given Observer may be observing many different
>>>objects.
>>>
>>>When an event is invoked, the Execute method of
>>>the observer is called. This method include as
>>>first argument a pointer to the "caller", which
>>>is a pointer to an itkObject.
>>>
>>>Observable objects *ARE NOT* responsible for the
>>>observer memory, not the other way around.
>>>
>>>What you point out, is rather a weakness in the
>>>implementation since the observables are assuming
>>>that the observers are still alive by the time the
>>>observable invokes an event. This may actually be
>>>considered a bug...
>>>
>>>
>>>So,.. there are two independent issues:
>>>
>>>1) Can Observers observe multiple object ?
>>>
>>> The answer is YES.
>>>
>>>
>>>
>>>2) Why do observables use a list of raw
>>> pointers instead of SmartPointers ?
>>>
>>> The answer is : This can be considered a bug.
>>> (or at least a weakness...)
>>>
>>>
>>>The fact that (2) uses raw pointers shouldn't be
>>>considered as an indication of (1).
>>>
>>>
>>>
>>> Regards,
>>>
>>>
>>>
>>> Luis
>>>
>>>
>>>
>>>===================
>>>Ziv Yaniv wrote:
>>>
>>>>Hi All,
>>>>
>>>>The following question is with regard to ITK, but it spills over to
>>>>IGSTK, so I'm sending it to this development list as I'm not on the ITK
>>>>developers one.
>>>>
>>>>I would like to understand the reasoning behind the design of the
>>>>ITK observer/observable pattern implementation. According to the
>>>>documentation of the AddObserver() method in itk::Object I cannot
>>>>have the same Observer attached to several objects, as observable
>>>>objects are responsible for the observer's memory. This is
>>>>reflected in the use of a raw pointer to a itk::Command object in
>>>>the itk::Object::AddObserver() method.
>>>>
>>>>In the spirit of ITK I expected the AddObserver method to receive
>>>>a SmartPointer which also allows a single observer
>>>>attached to multiple objects, as the memory would be released
>>>>when the last observable deleted its observers.
>>>>
>>>>Am I missing something? Should this go into a bug/feature request on
>>>>the ITK side?
>>>>
>>>> regards
>>>> Ziv
>>>>_______________________________________________
>>>>IGSTK-Developers mailing list
>>>>IGSTK-Developers at public.kitware.com
>>>>http://public.kitware.com/cgi-bin/mailman/listinfo/igstk-developers
>>>>
>>>
>>
>
>
More information about the IGSTK-Developers
mailing list