Tulip
4.3.0
Better Visualization Through Research
|
#include <Observable.h>
Inherited by tlp::AcyclicTest [private]
, tlp::BiconnectedTest [private]
, tlp::Camera, tlp::ConnectedTest, tlp::GlGraphComposite, tlp::GlScene, tlp::Graph, tlp::GraphNeedsSavingObserver [private]
, tlp::PluginLister, tlp::PropertyInterface, and tlp::View.
Public Member Functions | |
void | addListener (Observable *const listener) const |
void | addObserver (Observable *const observer) const |
unsigned int | countListeners () const |
unsigned int | countObservers () const |
unsigned int | getReceived () const |
unsigned int | getSent () const |
void | removeListener (Observable *const listener) const |
void | removeObserver (Observable *const observerver) const |
Static Public Member Functions | |
static Observable * | getObject (tlp::node n) |
static const tlp::VectorGraph & | getObservableGraph () |
static void | holdObservers () |
static bool | isAlive (tlp::node n) |
static unsigned int | observersHoldCounter () |
static void | unholdObservers () |
Protected Member Functions | |
Observable (const Observable &) | |
tlp::Iterator< tlp::Observable * > * | getObservables () const |
bool | hasOnlookers () const |
void | notifyObservers () |
void | observableDeleted () |
Observable & | operator= (const Observable &) |
void | sendEvent (const Event &message) |
virtual void | treatEvent (const Event &message) |
virtual void | treatEvents (const std::vector< Event > &events) |
Friends | |
class | Event |
The Observable class is the base of Tulip's observation system.
Each class that wishes to send or receive notifications needs to inherit from Observable.
Tulip has two separate mechanisms of observation, Observers and Listeners. These two mechanisms work through the same class, the difference lies in the way an Observer of Listener is attached to the object whose events it will receive.
The Listener is closer to the original pattern, where events are sent directly to the recipient. The Observer is a twist for performance purposes, it can receive the events in a delayed fashion, and cannot know if the event was just sent or was delayed.
The purpose of this twist is to allow algorithms that perform a high number of modifications (e.g. creating a grid to route edges, creating multiple subgraphs with metrics or layouts) to run smoothly without overcrowding the event queue. As events are sent for every graph modification (e.g. adding a node, deleting a node, setting a value on a node), the sheer quantity of events sent by these algortithms would cause a big performance hit.
This is avoided by using Observable::holdObservers(). This holds all events in a queue and only sends them when Observable::unholdObservers() is called.
The only exception to this mechanism is the Event::DELETE kind of event, that is never held back. Think of it as an unmaskable POSIX signal; whatever the connection to the object and the state of holdObserver, this event will get through. This is used to prevent crashes in the case where and object is listened or observed and is deleted, as it is likely the recipient keeps a pointer to the now deleted object.
The Listener however is not affected by the use of Observable::holdObservers() and Observable::unholdObservers().
The observables Observers and Listeners are internally stocked in a Graph structure, allowing to visualize the connections easily. This eases debugging of Observation-related bugs.
Events are always sent to Listeners first, and then to Observers, even when there is no hold.
If you wish to receive events, you must inherit from Observable, and implement one of two virtual functions.
If you need to received events without delay, you will be a Listener, and need to implement treatEvent(). You will attach to the object you wish to receive events from using addObserver().
If you can receive events after a delay, you will be an Observer, and need to implement treatEvents(). You will attach to the object you wish to receive events from using addListener().
Definition at line 123 of file Observable.h.
void tlp::Observable::addListener | ( | Observable *const | listener | ) | const |
addListener Adds a Listener to this object.
The Listener will receive events regardless of the state of holdObservers() and unholdObservers().
listener | The object that will receive events. |
void tlp::Observable::addObserver | ( | Observable *const | observer | ) | const |
addObserver Adds an Observer to this object.
The observer will receive events sent by this object, if there is no hold applied.
observer | The object that will receive events. |
unsigned int tlp::Observable::countListeners | ( | ) | const |
countListeners gets the number of listeners attached to this object.
unsigned int tlp::Observable::countObservers | ( | ) | const |
countObservers gets the number of observers attached to this object.
|
static |
getObject Internal function for debugging.
If called during an update, it is possible the pointed object has been deleted. use isAlive() to check for this and avoid a crash.
n | The node representing the object to retrieve. |
|
static |
getObservableGraph Gets the observation graph.
|
protected |
use for old observer tulip compatibility
unsigned int tlp::Observable::getReceived | ( | ) | const |
getReceived get the number of received events.
unsigned int tlp::Observable::getSent | ( | ) | const |
getSent gets the number of sent events.
|
protected |
hasOnlookers Checks whether there are Observers/Listeners attached to this object.
Using this function avoids the creation of events that no-one will see :
|
static |
Holds back all events until Observable::unholdObservers() is called.
Listeners are not affected by this function. Once this function is called, all events heading to an Observer will be held, except DELETE events. The events are stored in a queue, and will be sent once Observable::unholdObservers() is called.
It is possible to nest calls to Observable::holdObservers() and Observable::unholdObservers(), and in this case the events will only be sent when there have been as many calls to Observable::unholdObservers() as to Observable::holdObservers().
It is possible to check whether the events are being help by checking the Observable::observersHoldCounter() function.
|
static |
isAlive Internal function for debugging.
If there is no hold curretly applied, or no update ongoing, always returns true. Checks if the object represented by the node has been deleted.
n | The node to check for life signs. |
|
protected |
use for old observer tulip compatibility
|
protected |
Sends the Event::DELETE before the deletion of the subclass and its internal objects.
The observation system automatically sends the DELETE event when the Observable is deleted, but in the case you need to access members of the class inheriting from Observable, you need the event sent before the outermost objects are destroyed.
To achieve this, you can call this function in your destructor, and the DELETE event will be sent. This will allow your Listeners/Observers to access your members one last time before deletion.
|
inlinestatic |
observersHoldCounter gives the number of times holdObservers() has been called without a matching unholdObservers() call.
Definition at line 160 of file Observable.h.
void tlp::Observable::removeListener | ( | Observable *const | listener | ) | const |
removeListener Removes a listener from this object.
The listener will no longer receive events from this object.
listener | The listener to remove from this object. |
void tlp::Observable::removeObserver | ( | Observable *const | observerver | ) | const |
removeObserver Removes an observer from this object.
The observer will no longer receive events from this object.
observer | The observer to remove from this object. |
|
protected |
sendEvent Sends an event to all the Observers/Listeners. It is higly recommended to check if there are observers/listeners to send the event to before actually sending it to avoid the overhead of creating too many objects.
This can be achieved by using the hasOnLookers() function :
message | The message to send to the listeners/observers. |
|
protectedvirtual |
treatEvent This function is called when events are sent to the Listeners, and Listeners only.
Is it passed a reference to the event that just happened.
message | The event that was sent. |
|
protectedvirtual |
treatEvents This function is called when events are sent to Observers, and Observers only.
It is passed a vector of all the events that happened since the last call. If events were held, this vector can be pretty large, and if events were not held it is likely it only contains a single element.
events | The events that happened since the last unHoldObservers(). |
Reimplemented in tlp::View, and tlp::GraphNeedsSavingObserver.
|
static |
Sends all held events to the Observers.
Listeners are not affected by this function.
In debug mode, if the hold counter is less than one when calling this function, an ObservableException will be raised.