[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