|
The TSE3 library uses a version of the "Observer" design pattern (GoF book), both as a part of it's public API and for internal implementation.
This design pattern is a framework for publishing information about events of interest. These events are multicast to every interested object. Objects can register an interest and revoke this at any time.
In the TSE3 implementation, the object which multicasts the events
is of the Notifier
class. Object which listen to these
events are Listener
classes.
These classes are documented fully in the tse3/Notifier.h
header file. The system is flexible, and type safe. The multicast
'events' are implemented as callbacks on member functions. These
member functions may have any number of parameters of any type.
These methods are defined in abstract 'listener interfaces' (e.g.
SongListener
).
Notifier
framework
Essentially, for each specific Notifier
type an interface
class is defined. This interface describes each of the possible events that
may be emitted by that Notifier
. Let's call this interface
interface_type
.
Now a class that can emit events inherits from
Notifier<interface_type>
. The implementation of the
class can emit events by calling it's protected notify
method.
A class that listens to these events inherits from
Listener<interface_type>
. This means that it also
inherits the interface_type
, and so implements the
member functions that recieve events.
Now, a Listener
can register an interest in events
by calling Listener::attachTo
for the appropriate
Notifier
, and revoke this interest with
Listener::detachFrom
.
Note that callback handlers are called synchronously by the TSE3
library. This means that as soon as an event occurs (i.e.
Notifier::notify
is called) every attached listener's handler
function gets called immediately (well, one after the other). Following
this, the code that called notify
regains control.
This has some repurcussions on what you can/cannot do in an event handler. Since you are called in the context of the TSE3 library is best not to do too much processor intensive activity - you may cause TSE3 performance to drop.
The Notifier
framework allows you to safely attach
or detach
from Notifier
objects in an event
handler. This can be the currently notifying object.
Note that if you perform an operation that will itself raise an event (i.e.
perform a call to Notifier::notify
) in your event handler, the
new event will be passed around and handled completely before processing
returns control to the original event handler.
Calling TSE3 modifying methods (e.g. most methods whose name starts with
'set') may therefore be unwise since they will probably perform a
notify
.
If the Transport
polling is run in a background thread, some
of your callbacks will be called in that thread's context. It may therefore
be unsafe to perform certain operations, GUI updating for example.
Listener
header files
The Listener
interface classes for each of the TSE3 classes is
in the listen
subdirectory. For example the
Transport
class is defined in tse3/Transport.h
.
However, it's Listener
interface class is defined in
tse3/listen/Transport.h
.
Each Listener
class header both defines the callback interface
and forward declares the relevant Notifier
type. Using these
headers you can therefore avoid large include file depenancy in your own
project header files.
In TSE3 versions 0.0.12 and later the Notifier
framework is
considerably improved. The system is now a lot more safe, elegant and above
all easy to use.
TSE3 version 0.0.22 saw some fixes to the Notifer framework that allows
you to safely call attach
and detach
in event
handlers.
Notifier.h
for definitions
of the notifier framework classes.
The classes are described in the KDOC class documentation:
|