[Insight-developers] Command / Observer / Event

Miller, James V (Research) millerjv@crd.ge.com
Thu, 2 May 2002 08:58:23 -0400


I agree with Lydia.  I think an Observer should be able 
to modify the object it is observing.  I have used StartEvents
as a mechanism for something external to the pipeline to
set ivars on an ProcessObject.  For instance, I can use
the StartEvent as a mechanism to tie a parameter (say a float) 
calculated by one process object to a Set method on another
process object.

For instance, one filter may calculate a mean and variance
over an image.  These are floats or doubles.  Since we have 
yet to wrap simple types as pipelinable data objects, I use
the StartEvent of a filter to go query the mean and variance
calculated by a filter before it in the pipeline.  This way, 
I know every time my second filter executes it has the most
recent values of the mean and variance from the filter before it.

There also shouldn't be a problem with an observer calling 
an Update().  The pipeline keeps track of whether it is currently
updating and should exit out of a second Update().

Luis, have you verified that your example is indeed a problem?

> Filter says to command: I'm going to start
> Command says to filter: Start.
> Filter says to command: I'm going to start
> Command says to filter: Start.
> Filter says to command: I'm going to start...
> 

I also don't think we should limit the observers to 
"small tasks that update a GUI".  They should be a general
mechansism that allows ITK to be interfaced to other systems.



-----Original Message-----
From: Lydia Ng [mailto:lng@insightful.com]
Sent: Wednesday, May 01, 2002 7:18 PM
To: Luis Ibanez; Insight Developers
Subject: RE: [Insight-developers] Command / Observer / Event


> Observers should not be able to modify the
> observed Object..... because that will
> trigger a ModifiedEvent while we are still
> in the middle of processing the list of
> events on this object.
>

Why not?

I currently have two applications (one inside the toolkit
and one outside) that rely on this functionality.

[1] I have an observer that externally monitors the progress of
some algorithm. If it satisfies some requirement, the
the observer tells the subject to stop via some
m_Subject->Stop() routine. 
For example, a GUI updates some display
and when the user is satified they can hit some button
and that will trigger the algorithm to stop nicely.

[2] For the multi-resolution, I think I was Stephen who
suggested it would be nice to have the ability to swap
registration components around, change parameters etc
at the beginning of each resolution level. 
This is what I have implemented. 
This is the mechanism which I use to alter parameters
at each resolution level.

I think one definitely have to have a mechanism for the
GUI to talk back and control the filter. So that one
can respond to cancel, change in parameters etc

I have used observers in this way because that is what I thought
they were for. I liked this way of handling the GUI-filter 
communication because there is good decoupling so I can
fairly easier tied filter to different GUIs.

Please don't take this away dear const meister!

- Lydia

> -----Original Message-----
> From: Luis Ibanez [mailto:luis.ibanez@kitware.com]
> Sent: Wednesday, May 01, 2002 3:32 PM
> To: Insight Developers
> Subject: [Insight-developers] Command / Observer / Event
> 
> 
> 
> Hi,
> 
> This is a proposal for a change in the
> current structure of the Command/Events
> management in ITK.
> 
> ------
> 
> The current implementation of the Observer
> Pattern in ITK is represented in the figure
> below.(Fig.1) The itk::Command classes play
> the role of Observers while the itk::Object
> play the role of Subjects.
> 
> Subjects send messages to observers by
> invoking Events.
> 
>  +----------+   Event    +----------+
>  | Subject  |----------->| Observer |
>  +----------+            +----------+
> 
> (Figure 1.)
> 
> This was initially introduced as hook where
> GUI interaction could be connected.  The events
> allowed to update the GUI as changes in the
> pipeline occur.
> 
> Every itk::Object has a list of
> pairs :  <Event, Observer *>
> 
> These pairs are created in the itk::Object
> by the method
> 
>     AddObserver(Event, Command *)
> 
> 
> When the Subject (any itk::Object) is running
> it may decide to send messages in order to
> inform others about their internal state.
> When the Subject invoke an event, it goes
> through its list of pairs and for every
> event that matches the type of the invoked
> event, it will call the  associated observer
> Execute() method.
> 
>  +-----------------------+
>  | Subject = itk::Object |
>  +-----------------------+
>     |
>     |----< ModifiedEvent, Observer_1 >
>     |
>     |----< ModifiedEvent, Observer_2 >
>     |
>     |----< DeleteEvent  , Observer_3 >
>     |
>     |----< StartEvent   , Observer_4 >
>     |
>     |----< EndEvent,      Observer_5 >
>     |
> 
> (Figure 2)
> 
> This mechanisms allows to interconect the
> system yet allowing decoupling since Subject
> don't need to know about observers. The mechanism
> of Events is relatively independent of the
> control of the pipeline. They are only related
> by the fact that some standard Pipeline methods
> InvokeEvents as part of they action.
> 
> As in the management of Event in GUI's,
> the spirit of the ITK Event is that they
> are just carring information out of the
> pipeline. They are not intended to control
> de pipeline itself. 
> 
> Because of the linear execution of the
> events in the list. It is not desirable
> that the Execute() method of an Observer
> could trigger the Invokation of other
> Events.  The execute method should be
> as rapid and passive from the point of
> view of the Pipeling.  For example, we
> should not call and Update() from the
> Execute method of a Command.
> 
> Imaging for example:
> 
> Filter1->AddObserver( StartEvent, Command )
> 
> if the execute method of the command,
> can end up calling directly or indirectly
> the Update() method of Filter1, it will
> enter in an infinite loop with the following
> dialog:
> 
> Filter says to command: I'm going to start
> Command says to filter: Start.
> Filter says to command: I'm going to start
> Command says to filter: Start.
> Filter says to command: I'm going to start...
> 
> So,... 
> 
> The proposed change in the current mechanism
> is intended to make sure that Observers can
> only be passive elements on the pipeline.
> A first step on this direction is of course:
> 
>    Const-correctness !
> 
> Observers should not be able to modify the
> observed Object..... because that will
> trigger a ModifiedEvent while we are still
> in the middle of processing the list of
> events on this object.
> 
> A more direct way of enforcing pasivness on
> the Observers is not even pass to them the
> pointer to the Subject, only the type of
> event.  In that way the command will just
> blindly execute an action on its side.
> In this options, particular commands that
> actually have to query the state of the
> observed object will have to be created
> as a specialized type of observer and will
> probably keep a internal Constsmart pointer
> to the observed object (the Subject).
> 
> 
> Observers that observe multiple object will
> not be selective. The will react in the
> same way to the received Event no matter
> who send it.  If multiple behaviors are
> required, multiple observers should be
> created.
> 
> 
> Observers are mostly used in examples
> an in some tests that monitor the progress
> of filter execution.
> 
> Does anybody see potential conflicts
> with doing these changes ?
> 
> 
> 
> 
>    Luis
> 
> 
> 
> _______________________________________________
> Insight-developers mailing list
> Insight-developers@public.kitware.com
> http://public.kitware.com/mailman/listinfo/insight-developers
> 
> 
_______________________________________________
Insight-developers mailing list
Insight-developers@public.kitware.com
http://public.kitware.com/mailman/listinfo/insight-developers