The SRUtil.Event library is an implementation of an event propagation system. An event provider emits event (such as 'the mouse position has been changed' in GUI applications) and event consumers react to it.
An event producer provides an event_source
object. Event consumer
provides an event_sink
(it can be a callback interface,
various kinds of delegates, etc). An event sink may be
connected to event_source
by event_binder
. When an
event provider emits an event, each of the bound event sinks gets a
control.
An event_source
and an according event_binder
are
parametrized by a sink_type
type, which must satisfy the following
conditions:
sink_type()
produces an empty value.
sink_type
has implicit conversation to the bool
type.
The expression
if
(sink) {/*...*/}
allows to execute the
code if and only if the sink
isn't an empty value. A sink which is
bound to something mustn't be converted to
true
.
Following entities satisfies these conditions: pointers (to an object and to a
code), boost::function
and srutil::delegate
.
A connection between an event producer and an event consumer exists since they
are bound by the method event_binder::bind
until
an invokation of the method event_binder::unbind
or
destroying of the event_binder
or the event_source
.
An event_binder
may be safely disconnected even during
event emiting (the binder may be destroyed or unbound), but the event_source
mustn't (in the current implementation).
template <typename TSink> class event_source
{
public:
typedef TSink sink_type;
typedef event_binder<sink_type> binder_type;
template <class TInvoker>
void emit(TInvoker const& invoker);
};
template <typename TSink> class event_binder
{
public:
typedef TSink sink_type;
typedef event_source<sink_type> source_type;
void bind(event_source const& source, sink_type sink);
void unbind();
};
class EventListener
{
public:
virtual void someMethod(int, int) = 0;
};
typedef srutil::delegate<void (int, int)> Delegate;
typedef srutil::event_source<EventListener*> EventSource1;
typedef srutil::event_source<Delegate> EventSource2;
EventSource1 e1;
EventSource2 e2;
e1.emit(boost::bind(&EventListener::someMethod, _1, 5, 10));
e2.emit(Delegate::invoker_type(5, 10));