TSE3 documentation Version 0.3.0 Index API  Version  Structure 

The Notifier/Listener Framework

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

How to use the 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.

What you can do in an event handler

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.

History

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.

See also

Notifier.h for definitions of the notifier framework classes.

The classes are described in the KDOC class documentation:

 © Pete Goodliffe, 2001-2003 Copyright Psalm 150