[Insight-developers] Command / Observer / Event

Luis Ibanez luis.ibanez@kitware.com
Wed, 01 May 2002 18:31:34 -0400


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