[IGSTK-Developers] Observer/Observable pattern

Luis Ibanez luis.ibanez at kitware.com
Mon Feb 26 09:57:20 EST 2007


Hi Ziv,


SmartPointers are so smart that they know
how to convert themselves to raw pointers   :-)


Please look at the code of the itk::SmartPointer
in the file


    Insight/Code/Common/itkSmartPointer.h


Lines 73-75:


     /** Return pointer to object.  */
     operator ObjectType * () const
       { return m_Pointer; }


This is the casting operator that converts a SmartPointer
into a raw pointer.


For more details on cast operators you may want to look
for example at:


  http://msdn2.microsoft.com/en-us/library/ts48df3y.aspx



     Regards,


        Luis



========================
Ziv Yaniv wrote:
> 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