Workspace 6.21.5
Public Member Functions | List of all members
ObserverSet Class Reference

Container for holding dynamically allocated observers. More...

#include <Workspace/DataExecution/Events/observerset.h>

Public Member Functions

 ObserverSet ()
 
 ~ObserverSet ()
 
template<typename EventIDSingletonType , typename ReceiverType , typename ReceiverOrBaseType , typename ReturnType >
Observeradd (Observable &sender, const EventIDSingletonType &eventId, ReceiverType &receiver, ReturnType(ReceiverOrBaseType::*func)(), bool threaded)
 
template<typename EventIDSingletonType , typename ReceiverType , typename ReceiverOrBaseType , typename ReturnType >
Observeradd (Observable &sender, const EventIDSingletonType &eventId, ReceiverType &receiver, ReturnType(ReceiverOrBaseType::*func)(), ObserverThreadType threaded=UnthreadedObserver)
 
template<typename EventIDSingletonType , typename ReceiverEventType , typename ReceiverType , typename ReceiverOrBaseType , typename ReturnType >
Observeradd (Observable &sender, const EventIDSingletonType &eventId, ReceiverType &receiver, ReturnType(ReceiverOrBaseType::*func)(const ReceiverEventType &), bool threaded)
 
template<typename EventIDSingletonType , typename ReceiverEventType , typename ReceiverType , typename ReceiverOrBaseType , typename ReturnType >
Observeradd (Observable &sender, const EventIDSingletonType &eventId, ReceiverType &receiver, ReturnType(ReceiverOrBaseType::*func)(const ReceiverEventType &), ObserverThreadType threaded=UnthreadedObserver)
 
void add (Observer *observer)
 
void clear ()
 
bool empty () const
 
Observeroperator[] (int i)
 
bool remove (Observable &subject)
 
bool remove (Observable &subject, const EventID &eventID)
 
void remove (Observer *observer)
 
unsigned size () const
 

Detailed Description

This class is useful for managing the lifetime of observers where the observers must be deleted when the receiving object is deleted. Clients add observers they dynamically allocate using the add() member function. If observers need to be deleted individually or before the container is deleted, the remove() member functions allows clients to destroy observers or just take back ownership.

The most common and useful way to use an ObserverSet is to hold an instance of one in the object that will receive the event notifications. By making the instance a member of the receiving object, the ObserverSet will be automatically deleted when the receiver is. Since the ObserverSet also deletes all observers it contains when it is itself deleted, this means that the lifetime of all observers added to such a set is handled automatically. Thus, if either the subject being observed or the receiver of the notifications is deleted, the observer will also be automatically deleted. This frees up developers from having to keep track of the order of destruction between observers, the things they are observing and the objects receiving the event notifications.

The one restriction is that all observers added to an ObserverSet must be dynamically allocated. This is normally easy, since by far the most common way to create an observer is with a call to one of the templated add() functions.

Constructor & Destructor Documentation

◆ ObserverSet()

Creates an empty observer set.

◆ ~ObserverSet()

The destructor deletes all observers currently held by the set.

Member Function Documentation

◆ add() [1/5]

Observer * add ( Observable sender,
const EventIDSingletonType &  eventId,
ReceiverType &  receiver,
ReturnType(ReceiverOrBaseType::*)()  func,
bool  threaded 
)
inline

◆ add() [2/5]

Observer * add ( Observable sender,
const EventIDSingletonType &  eventId,
ReceiverType &  receiver,
ReturnType(ReceiverOrBaseType::*)()  func,
ObserverThreadType  threaded = UnthreadedObserver 
)
inline

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ add() [3/5]

Observer * add ( Observable sender,
const EventIDSingletonType &  eventId,
ReceiverType &  receiver,
ReturnType(ReceiverOrBaseType::*)(const ReceiverEventType &)  func,
bool  threaded 
)
inline

◆ add() [4/5]

Observer * add ( Observable sender,
const EventIDSingletonType &  eventId,
ReceiverType &  receiver,
ReturnType(ReceiverOrBaseType::*)(const ReceiverEventType &)  func,
ObserverThreadType  threaded = UnthreadedObserver 
)
inline
Template Parameters
EventIDSingletonTypeThis is the type of the EventID subclass to be caught. In addition to this being a subclass of EventID, it must also have a typedef for EventType which specifies what event class is associated with it. In almost all cases, this is all handled transparently by making your event class derive from ObservableEventType and by calling that event type's eventID() function to provide the EventIDSingletonType needed for the second parameter to this function.
ReceiverEventTypeThis is the type for the receiver's parameter. It must be the same as EventIDSingletonType::EventType or be a base class of it. Failure to meet this requirement will result in the compiler discarding the templated add() functions from the possible set of matching functions, leaving only add(Observer*) as a candidate. The compiler will then complain and may include a note that only add(Observer*) can be found. In reality, it just means the ReceiverEventType did not match the sender event type. Note also that the other function template overload for add() provides support for receiver functions which take no parameter at all.
ReceiverTypeThe class type of the receiving object. This can be any class, but not a free function (it is trivial to wrap a free function inside a class object's member function).
ReceiverOrBaseTypeThis will be the class type whose member function will be called. In most cases, it will be the same as ReceiverType, but if the function to be called comes from a base class of ReceiverType then it will be different. We have to use a different template parameter for this to support such cases and still get automatic type deduction when calling the function without the template arguments being specified.
ReturnTypeThe return type of the receiver's member function. This is only used to allow arbitrary return types. The actual return type or return value is not used.
Parameters
senderThe object from which events are to be observed.
eventIdThe specific EventID to respond to.
receiverThe object be notified of the event.
funcThe member function to be called on the receiver.
threadedIf true, a threaded observer will be created. A threaded observer overrides Observer::updateInObserverThread() instead of Observer::update() to ensure that if the notification happens in a different thread to that in which the observer was created, the observer will be notified through its event loop rather than via a direct function call. The sender thread is blocked until the observer finishes handling the event notification.

Instances of this member function template will forward a specified event type from an Observable object to a designated receiver. The receiver can be of any class type. The event is forwarded to a designated non-const member function of the receiver, where that member function takes a single parameter of a type that matches the event being sent. The other template overload of add() allows for receiver member functions which take no parameters. In either case, the return value of the receiving function can be any type and is not used in any way.

Checks to ensure the receiver can accept the specified event type are all done at compile time. If the receiver member function's parameter does not match the event type, the compiler will complain that it could not find a match for the call to add(). It may claim that the only candidate is the non-template add() function taking only a single Observer parameter, but this is because none of the templated versions matched and the C++ rules allow non-instantiable template functions to be silently discarded from the set of potentially matching functions.

For observers where threaded is false, the update() member function is overridden. If, however, threaded is true, then the updateInObserverThread() member function is overridden instead.

Returns
A dynamically allocated Observer object which will have already been added to the observer set. The returned object should be destroyed by calling its destroy() member function, not by using operator delete on it.

◆ add() [5/5]

void add ( Observer observer)
Parameters
observerThe observer to add to the set.

The ObserverSet takes ownership of the observer. If it was part of a different observer set at the time of the call, the observer will be transferred from the old set to this one.

Client code would normally find it easier to call the templated overload of this function since it allows the observer to be created and added to the observer set all in one convenient call.

◆ clear()

void clear ( )

Deletes all observers held.

◆ empty()

bool empty ( ) const
Returns
True if the observer set is empty.

◆ operator[]()

Observer * operator[] ( int  i)
Parameters
iThe index of the observer to return.
Returns
The observer at the specified index.
Note
The range of i is only checked by asserts. Clients should perform their own checks to ensure that i refers to a valid index in the array of observers.

◆ remove() [1/3]

bool remove ( Observable subject)
Parameters
subjectAll observers for this subject will be removed as well as any that don't have a valid subject
Returns
True if any observers were found for the specified subject.

◆ remove() [2/3]

bool remove ( Observable subject,
const EventID eventID 
)
Parameters
subjectThe subject for which an observer should be removed.
eventIDThe event ID an observer should be observing.
Returns
True if any observers were found for the specified subject and eventID.

◆ remove() [3/3]

void remove ( Observer observer)
Parameters
observerThe observer to remove from the set.

◆ size()

unsigned size ( ) const
Returns
The number of observers currently held by the ObserverSet.