Difference between revisions of "Slicer3:EventBroker"
Line 51: | Line 51: | ||
* add a timer to log the amount of time taken to process each event | * add a timer to log the amount of time taken to process each event | ||
+ | |||
+ | See the file Libs/MRML/vtkEventBroker.h for more information on logging options and introspection features. | ||
==References== | ==References== |
Revision as of 20:28, 4 April 2008
Home < Slicer3:EventBrokerContents
Currently
The basic idea of the EventBroker is that currently we have a lot of this kind of code in GUIs:
node->AddObserver(vtkCommand::ModifiedEvent, callbackCommand)
Problems
The problems with this:
- node 'owns' the observer, but the callbackCommand is opaque so it doesn't know anything about what will happen when the event is invoked
- the GUI needs to explicitly remove the observer before it is destroyed
- node is not introspectable; you cannot get a list of observers on the node
- there's no easy way to know what side effects will happen for any Set call (either a priori or experimentally).
- there's no way to collapse events or disable them
EventBroker Solution
The EventBroker is a singleton, available as:
vtkEventBroker *broker = vtkEventBroker::GetInstance();
with the broker, you can make a call like the following:
broker->AddObservation(node, vtkCommand::ModifiedEvent, this, callbackCommand);
where node is the subject of the observation.
The broker does the following:
- adds DeleteEvent observers to both node and this so it can remove the observation automatically when either side is destroyed
- keeps an introspectable list of all observers it knows about
- has an option to keep a log of all event invocations for debugging and performance analysis
- has an option to turn off all event invocations
- has an asynchronous option to queue all event invocations and invoke them later (off by default)
- has option to collapse redundant events in the queue
The broker is also available for use from tcl. For convenience in slicer there's a global variable for the broker so you can use a code snippet like:
$::slicer3::broker AddObservation $node ModifiedEvent {puts "$node was modified"}
Future options include:
- add a timer to log the amount of time taken to process each event
See the file Libs/MRML/vtkEventBroker.h for more information on logging options and introspection features.
References
- Java Message Service (JMS) API
- Wikipedia definition of Observer Pattern
- A C++ implementation
- Another C++ implementation
- The Qt implementation
Dependency Graphs
EventBroker code should have the option to put out log files that are compatible with graphviz .dot file format. This can be rendered with a variety of programs, or even pasted directly in the wiki:
Simple Dependency
<graphviz border='frame' format='svg'> digraph G {
vtkImageViewer -> vtkImageEllipsoidSource[ label = ModifiedEvent ]
- }
</graphviz>
Subset of Slicer Dependencies
<graphviz border='frame' format='svg'> strict digraph G {
vtkMRMLModelDisplayNode -> vtkMRMLModelDisplayNode [ label = "ModifiedEvent" ]
- vtkMRMLScalarVolumeDisplayNode -> vtkMRMLScalarVolumeDisplayNode [ label = "ModifiedEvent" ]
- vtkMRMLLabelMapVolumeDisplayNode -> vtkMRMLLabelMapVolumeDisplayNode [ label = "ModifiedEvent" ]
- vtkMRMLDiffusionWeightedVolumeDisplayNode -> vtkMRMLDiffusionWeightedVolumeDisplayNode [ label = "ModifiedEvent" ]
- vtkMRMLDiffusionTensorVolumeDisplayNode -> vtkMRMLDiffusionTensorVolumeDisplayNode [ label = "ModifiedEvent" ]
- vtkMRMLFiberBundleLineDisplayNode -> vtkMRMLFiberBundleLineDisplayNode [ label = "ModifiedEvent" ]
- vtkMRMLFiberBundleTubeDisplayNode -> vtkMRMLFiberBundleTubeDisplayNode [ label = "ModifiedEvent" ]
- vtkMRMLFiberBundleGlyphDisplayNode -> vtkMRMLFiberBundleGlyphDisplayNode [ label = "ModifiedEvent" ]
- vtkMRMLCameraNode -> vtkOpenGLCamera [ label = "ModifiedEvent" ]
- vtkMRMLUnstructuredGridDisplayNode -> vtkMRMLUnstructuredGridDisplayNode [ label = "ModifiedEvent" ]
- vtkMRMLCameraNode -> vtkOpenGLCamera [ label = "ModifiedEvent" ]
- vtkMRMLModelDisplayNode -> vtkMRMLModelDisplayNode [ label = "ModifiedEvent" ]
- vtkMRMLCameraNode -> vtkOpenGLCamera [ label = "ModifiedEvent" ]
- vtkMRMLModelNode -> vtkPolyData [ label = "ModifiedEvent" ]
- vtkMRMLModelNode -> vtkPolyData [ label = "ModifiedEvent" ]
- vtkMRMLModelDisplayNode -> vtkMRMLModelDisplayNode [ label = "ModifiedEvent" ]
- vtkMRMLModelDisplayNode -> vtkImageData [ label = "ModifiedEvent" ]
- vtkMRMLModelNode -> vtkPolyData [ label = "ModifiedEvent" ]
- vtkMRMLModelDisplayNode -> vtkMRMLModelDisplayNode [ label = "ModifiedEvent" ]
- vtkMRMLModelDisplayNode -> vtkImageData [ label = "ModifiedEvent" ]
- vtkMRMLModelNode -> vtkPolyData [ label = "ModifiedEvent" ]
- vtkMRMLModelDisplayNode -> vtkMRMLModelDisplayNode [ label = "ModifiedEvent" ]
- vtkMRMLModelDisplayNode -> vtkImageData [ label = "ModifiedEvent" ]
- }
</graphviz>
Issues
- how to work with the vtkObserverManager?