/**
\page PluginFramework_EventAdmin_Page Event Admin
The Event Admin Service Specification, part of the OSGi Compendium specification,
defines a general inter-plug-in communication mechanism. The communication conforms
to the popular publish/subscribe paradigm and can be performed in a synchronous
or asysnchronous manner.
The main components in a publish/subscribe communication are:
- Event Publisher - sends events or messages related to a specific topic
- Event Handler (or Subscriber) - expresses interest in one or more topics and
receives all the messages belonging to such topics.
Events are composed of two attributes:
- A \b topic defining the nature of the event. Topic names are usually arranged in a hierarchical namespace, where slashes are used to separate the levels (i.e. "org/commontk/PluginFrameworkEvent/STARTED") and
- A set of \b properties describing the event.
Read the
EventAdmin Service Specifications (Chapter 113) for an in-depth explanation.
\section EventAdmin_CreatePublisher Creating an Event Publisher
An event publisher can either be a simple C++ class that creates events and sends
them using the ctkEventAdmin
service interface or a Qt signal which
is registered as a "publisher" using the ctkEventAdmin
service
interface.
\subsection EventAdmin_CreatePublisher_Class Using a simple C++ class
The publisher is a function which creates a ctkEvent
object and
sends it by using the ctkEventAdmin
service interface.
\snippet EventAdmin-Intro/ctkSnippetReportManager.h Publish event
The ctkEventAdmin::sendEvent()
method sends the ctkEvent
object synchronously. To send it asynchronously, use the ctkEventAdmin::postEvent()
method, such as:
\snippet EventAdmin-Intro/ctkSnippetReportManager.h Publish event async
Synchronous event delivery is significantly more expensive than asynchronous
delivery. Even for synchronous delivery event notifications could be
handled in a separate thread (depending on the EventAdmin implementation). This
implies that sendEvent()
callers should generally not hold any
locks when calling this method. Asynchronous delivery should be preferred
over the synchronous delivery.
\subsection EventAdmin_CreatePublisher_Signal Using a Qt signal
Using a Qt signal to publish an event requires declaring a signal and registering (publishing)
it with the Event Admin:
\snippet EventAdmin-Intro/ctkSnippetReportManager.h Declare signal
Register the signal using a specific topic (emitting the signal will always send
ctkEvent
objects with this topic as EVENT_TOPIC
property):
\snippet EventAdmin-Intro/ctkSnippetReportManager.h Register signal
Emitting the signal will automatically create a ctkEvent
object, sending
it synchronuously or asynchronuously, depending on the Qt::ConnectionType used when
publishing the signal.
\snippet EventAdmin-Intro/ctkSnippetReportManager.h Emit signal
\subsection EventAdmin_CreatePublisher_Compare Comparison
The act of sending an event is simplified by using a Qt signal, after it was registered
with the Event Admin. However, the Qt signal approach is less performant since the
signal emission needs to go through the Qt meta object system. Further, the signal is
tied to a specific event topic.
\section EventAdmin_CreateHandler Creating and registering an Event Handler
An event handler can either be a class implementing the ctkEventHandler
interface which is registered as a service object or a Qt slot which is registered
with the Event Admin (subscribed to certain topics).
Event handlers should not spend too long in the event handling method. This will
prevent other handlers from being notified. Long running operations should be executed
in their own thread.
Note that in general, your event handling code will be called from a separate thread.
\subsection EventAdmin_CreateHandler_Service Event Handler as a Service
Create an event handler by implementing the ctkEventHandler
interface:
\snippet EventAdmin-Intro/ctkSnippetReportManager.h Event Handler service
To receive event notifications, the event handler must be registered as a service under the
ctkEventHandler
interface. When registering the service, a QString
or QStringList
property named EVENT_TOPIC
must be specified. This
property describes the list of topics in which the event handler is interested. For example:
\snippet EventAdmin-Intro/main.cpp Event Handler service registration
It is possible to use '*' as a wildcard in the final character of the EVENT_TOPIC
:
\snippet EventAdmin-Intro/main.cpp Event Handler service registration wildcard
Finally, it is possible to specify an additional EVENT_FILTER
property to filter
event notifications. The filter expression follows the normal LDAP syntax:
\snippet EventAdmin-Intro/main.cpp Event Handler service registration filter
\subsection EventAdmin_CreateHandler_Slot Event Handler as a Qt slot
Every Qt slot taking a ctkEvent
object as an argument can be subscribed to
receive event notifications. For example, a slot like
\snippet EventAdmin-Intro/ctkSnippetReportManager.h Event Handler slot
can be subscribed to receive events like
\snippet EventAdmin-Intro/main.cpp Event Handler service registration slot
You can use the same expressions for EVENT_TOPIC
and
EVENT_FILTER
as in the examples above for registering the event
handler as a service object implementing ctkEventHandler
.
Using Qt slots as Event Handlers will makes it easy to ensure that the event
handling code is executed in the receiver's thread (the default connection type
is Qt::AutoConnection).
\subsection EventAdmin_CreateHandler_Compare Comparison
Registering an event handler using either the ctkEventHandler
interface or
a Qt slot involves approximately the same amount of code. However, using slots
will be less performant (which might be neglectable, depending on your use case) but the
code will be automatically synchronized with the receiver thread.
Further, subscribing slots means that you require a registered Event Admin service implementation.
The ctkEventHandler
approach does not need to know anything about the Event
Admin, since you register your handler as a service object in the framework.
*/