BDE 4.14.0 Production release
|
Provide an implementation of a managed signals and slots system.
This component provides the template class bdlmt::Signaler<t_PROT>
, an implementation of a managed signal and slots system for the void returning function prototype t_PROT
. Each signaler represents a callback with multiple targets (called "slots") which are invoked in a known order when the signaler is invoked (called being "emitted").
A slot being connected to a signaler is represented by a bdlmt::SignalerConnection
which can be used to disconnect that connection at any time, but can also be discarded if managing the lifetime of the individual connection is not needed. A guard to disconnect a slot on its destruction is available in bdlmt::SignalerConnectionGuard
.
Signalers and the slots connected to them are all managed. Any connections will be automatically disconnected when a Signaler
is destroyed, or when explicitly disconnected, and all internally allocated resources will be destroyed when no more references to them remain. This enables the user to make signaler/slot connections and emit signals without expanding effort on managing the lifetimes of any of the involved objects.
Slots connected to a signaler Signaler<t_PROT>
must be callable and copyable objects that may be passed to the constructor of bsl::function<t_PROT>
. I.e. a slot must be callable with the same arguments as t_PROT
, and if a slot returns a value it will be discarded.
Slots are free to have side effects, which means that some slots may have to be called before others even if they are not connected in that order. bdlmt::Signaler
allows slots to be placed into groups that are ordered in some way. Group values are integers, and are ordered by the integer <
relation. By default, all connected slots have the group value set to 0.
Within a single thread of execution slots are always executed in the order defined by their respective groups and, within groups, by the order they were connected to the signaler. If the signaler's call operator is invoked concurrently from multiple threads, slots may also be executed concurrently.
Internally, bdlmt::Signaler
stores copies of connected slot objects. The copy of the slot object is destroyed after the slot is disconnected from the signaler, or after the signaler is destroyed, but the exact moment is unspecified. It is only guaranteed that the lifetime of such object will not exceed the collective lifetime of the signaler and all connection objects associated with to that signaler.
Ordering comparisons of SignalerConnection
s are transitive and are provided to facilitate their being stored in an associative container. The ordering of a SignalerConnection
does not change when it is disconnected.
In equality comparisons, two default constructed connections compare equivalent and a default constructed connection is never equivalent to a connection to a slot. If a connection is not default constructed, it is equivalent only to another connection that refers to the same slot.
bdlmt::Signaler
is fully thread-safe, meaning that multiple threads may use their own instances of the class or use a shared instance without further synchronization.
With the exception of assignment operators, swap()
, reset()
and release()
member functions, bdlmt::SignalerConnection
and bdlmt::SignalerConnectionGuard
are thread-safe, meaning that multiple threads may use their own instances of the class or use a shared instance without further synchronization.
It is safe to access or modify two distinct connection objects simultaneously, each from a separate thread, even if they represent the same slot connection.
Suppose we want to implement a GUI button class that allows users to keep track of its press
events.
First, we declare the class
:
Then, we define its methods:
Next, we provide an event handler callback printing its argument, which the class will pass the number of times the button has been pressed:
Then, in main
, create a button and subscribe to its events.
Next the button is "pressed", we will receive a notification.
Now, we see the following message:
Finally, unsubscribe from button's events when we don't want to receive notifications anymore. (If we didn't call disconnect
, button
would clean up all the allocated resources when it went out of scope):