Events
From IGSTK
Contents |
Definition
IGSTK uses ITK's event handling mechanism which, as stated in the ITK Software Guide, follows the "Subject/Observer" design. In this design, each time the "subject" invokes an event, the "observer" for that particular subject/event combination will be notified.
Some important points to note are:
- any itk Object (and hence any IGSTK object derived from an itk Object) can be a "subject"
- an "observer" will only observe one particular "subject"
- an "observer" only listens for one kind of event
- the usual action taken by the "observer" is to call a method of a third object
Caveat
The term "event" has multiple meanings for programmers, much like the similar terms "signal" and "message". Any reference to "event" in the following discussion should be taken to mean an itk::EventObject. No other meaning is implied, nor should any other meaning be construed.
Use of Events in IGSTK
The best way to illustrate the use of events is with an example. The following code is from igstkView.cxx:
m_PulseGenerator = PulseGenerator::New(); m_PulseObserver = ObserverType::New(); m_PulseObserver->SetCallbackFunction( this, & View::RefreshRender ); m_PulseGenerator->AddObserver( PulseEvent(), m_PulseObserver );
- The PulseGenerator is the "subject", it is the entity that is generating the events.
- The PulseObserver is the "observer", the ObserverType is typedef'd to itk::SimpleMemberCommand<igstk::View>
- The action that will be taken by the observer is to call this->RefreshRender(), where "this" is the View object.
- The observer is registered to listen for the PulseGenerator's PulseEvent
The result of the above code is that every time the PulseGenerator invokes a PulseEvent, the view's RefreshRender() method will be called. The RefreshRender() method takes no arguments.
Now that we have had an example of how the PulseEvent can be "observed", we also need an example of how the event is "invoked". The following code is from igstkPulseGenerator.cxx:
this->InvokeEvent( PulseEvent() );
In the above code, "this" is the PulseGenerator object. The PulseGenerator inherits the InvokeEvent() method, as well as the AddObserver() method of the previous example, from the itk::Object base class.
Notes on Events
- Multiple observers can be registered to a particular subject/event combination.
- When InvokeEvent() is called, the observers' callbacks are executed in the order in which they were registered with AddObserver()
- There is no way, other than changing the order in which observers are added, to control the order in which observers are called (i.e. there is no way of setting different priorities for different observers)
- The call to InvokeEvent() does not return until all the callbacks have been executed, and
- The callback functions are always executed within the same thread from which InvokeEvent() was called
Event Taxonomy
Events in IGSTK follow a hierarchy. The root of the hierarchy is IGSTKEvent. If an observer is registered with an object to listen for a particular event, it will also be notified if any events derived from that event are invoked.
The basic event types used by IGSTK are defined in igstkEvents.h:
- PulseEvent
- RefreshEvent
There should probably also be FailureEvent to mark that an error occurred, and a corresponding SuccessEvent to mark that a desired result was achieved with no error.
Individual IGSTK classes can define their own events, but should always derive their events from one of the events defined in igstkEvents.h.
