Tulip  4.6.0
Better Visualization Through Research
tlp::Observable Class Reference

#include <Observable.h>

+ Inheritance diagram for tlp::Observable:

List of all members.

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 tlp::node getNode (const tlp::Observable *obs)
static ObservablegetObject (tlp::node n)
static const tlp::VectorGraph & getObservableGraph ()
static unsigned int getScheduled (tlp::node n)
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 ()
Observableoperator= (const Observable &)
void sendEvent (const Event &message)
virtual void treatEvent (const Event &message)
virtual void treatEvents (const std::vector< Event > &events)

Friends

class Event

Detailed Description

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 or a 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 algorithms would cause a big performance hit.

This can be 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 observable Observers and Listeners are internally store in a Graph structure, allowing to easily visualize their connections. 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 addListener().

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 addObserver().

Definition at line 123 of file Observable.h.


Member Function Documentation

void tlp::Observable::addListener ( Observable *const  listener) const

Adds a Listener to this object.

The Listener will receive events regardless of the state of holdObservers() and unholdObservers().

Parameters:
listenerThe object that will receive events.
void tlp::Observable::addObserver ( Observable *const  observer) const

Adds an Observer to this object.

The observer will receive events sent by this object, if there is no hold applied.

Parameters:
observerThe object that will receive events.
unsigned int tlp::Observable::countListeners ( ) const

gets the number of listeners attached to this object.

Returns:
the number of listeners attached to this object.
unsigned int tlp::Observable::countObservers ( ) const

gets the number of observers attached to this object.

Returns:
the number of observers attached to this object.
static tlp::node tlp::Observable::getNode ( const tlp::Observable obs) [static]

internal function for debugging purpose Get the node representing this object in the Observable Graph.

Parameters:
obsthe Observable object
Returns:
the node of the Observable object in the Observable Graph.

internal function for debugging purpose If called during an update, it is possible the pointed object has been deleted. use isAlive() to check for this and avoid a crash.

Parameters:
nThe node representing the object to retrieve.
Returns:
The object represented by the node.
static const tlp::VectorGraph& tlp::Observable::getObservableGraph ( ) [static]

Gets the observation graph.

Returns:
The graph containing a node for each Observable/Observer/Listener, and an edge between connected objects.
tlp::Iterator<tlp::Observable *>* tlp::Observable::getObservables ( ) const [protected]

use for old observer tulip compatibility

unsigned int tlp::Observable::getReceived ( ) const

get the number of received events.

Returns:
the number of received events (0 when compiling with -DNDEBUG).
static unsigned int tlp::Observable::getScheduled ( tlp::node  n) [static]

internal function for debugging purpose getScheduled get the number of scheduled events for this Observable.

Parameters:
nThe node of an Observable object
Returns:
the number of scheduled events involving this Observable as sender or receiver.
unsigned int tlp::Observable::getSent ( ) const

gets the number of sent events.

Returns:
the number of sent events (0 when compiling with -DNDEBUG).
bool tlp::Observable::hasOnlookers ( ) const [protected]

Checks whether there are Observers/Listeners attached to this object.

Using this function avoids the creation of events that no-one will see :

    if (hasOnlookers()) {
       sendEvent(GraphEvent(*this, GraphEvent::TLP_ADD_NODE, n));
    }
Returns:
static void tlp::Observable::holdObservers ( ) [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.

See also:
unholdObservers
observersHoldCounter
static bool tlp::Observable::isAlive ( tlp::node  n) [static]

internal function for debugging purpose If there is no hold currently applied, or no update ongoing, always returns true. Checks if the object represented by the node has been deleted.

Parameters:
nThe node to check for life signs.
Returns:
Whether the node is dead.
void tlp::Observable::notifyObservers ( ) [protected]

use for old observer tulip compatibility

void tlp::Observable::observableDeleted ( ) [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.

Warning:
This function must be called only once per object. Make sure no other class in the inheritance tree calls this function before adding this call to your destructor.
static unsigned int tlp::Observable::observersHoldCounter ( ) [inline, static]

observersHoldCounter gives the number of times holdObservers() has been called without a matching unholdObservers() call.

Returns:
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

Removes a listener from this object.

The listener will no longer receive events from this object.

Parameters:
listenerThe listener to remove from this object.
void tlp::Observable::removeObserver ( Observable *const  observerver) const

Removes an observer from this object.

The observer will no longer receive events from this object.

Parameters:
observerThe observer to remove from this object.
void tlp::Observable::sendEvent ( const Event message) [protected]

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 :

    if (hasOnlookers()) {
       sendEvent(GraphEvent(*this, GraphEvent::TLP_ADD_NODE, n));
    }
Parameters:
messageThe message to send to the listeners/observers.
virtual void tlp::Observable::treatEvent ( const Event message) [protected, virtual]

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.

Parameters:
messageThe event that was sent.

Reimplemented in tlp::View.

virtual void tlp::Observable::treatEvents ( const std::vector< Event > &  events) [protected, virtual]

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.

Parameters:
eventsThe events that happened since the last unHoldObservers().

Reimplemented in tlp::View, and tlp::GraphNeedsSavingObserver.

static void tlp::Observable::unholdObservers ( ) [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.

See also:
holdObservers
observersHoldCounter
 All Classes Files Functions Variables Enumerations Enumerator Properties