Signal
is templated by the argument types that must be passed when
triggering, and that will be transmitted to subscribers. For instance,
Signal<int,
int>
is the type of a
Signal
with two ints as payload type:
Signal::operator()
will expect two ints, and subscribers will be expected to
have signature
void(int,
int)
.

Note

The types used as template arguments to signal must be registered to the type
system. If you fail to do that, you will get errors like:

The variadic form of
connect
works in a similar manner to
boost::bind()
: values passed to
connect
will be passed to the function,
in order, and placeholders
_1
,
_2
... will be replaced by the signal
payloads.

This form will also recognize if the first argument is a
boost::weak_ptr
,
or if it as pointer to a class inheriting from
qi::Trackable
. In both cases,
the subscriber will be automatically disconnected if the pointer cannot be
locked. See
this example
for a demonstration of that
very same mechanism in
qi::Future
.

Unregistering a subscriber is done by invoking
Signal::disconnect
with a
SignalLink
as its sole argument. The call will block until all currently
running invocations of the subscriber have finished. This gives you the strong
guarantee than once
disconnect
has returned, your callback function is not
being called, and will never be called again.

Warning

disconnect
is a blocking method which will wait for the callback to finish
(except if it’s called from withing the callback). The signal destruction is
also blocking. These two cases may cause deadlocks in your code, be careful.

It is
very dangerous
to set the call type to Direct as your function may
block the code that triggers the signal. This type of call is only useful for
optimization purposes, only for very small and fast fuctions that do not
lock.

Sometimes, mainly for performance reasons, it is useful to only enable some
code if a
Signal
has at least one subscriber. For example, if you have a
signal
humanDetected
, you may want to enable the image processing code only
if there is at least one subscriber to the signal to save CPU cycles.

This can be achieved by passing a callback to the
Signal
constructor, of
signature
void(bool)
. This function will be called
synchronously
each
time the number of subscribers switches between 0 and 1.

Sometimes, mainly when bridging
Signal
with another signal implementation,
one needs to override the action performed when the signal is triggered (which
is by default to invoke all subscribers).

This can be achieved by inheriting from
Signal
, and then either overriding
the
trigger
virtual function, or by calling
setTriggerOverride
with a
functor that will replace the original trigger. You can then call
callSubscribers
to invoke the subscribers, which
trigger
would do
by default.

a SignalSubscriber object. This object can be implicitly converted to a SignalLink.

Connect a subscriber to this signal.

Multiple forms can be used:
connect(function, argOrPlaceholder1, argOrPlaceholder2, ...) Where function is a function or callable object (such as a boost::function). If the first argument is a weak ptr or inherits qi::Trackable, the slot will automatically disconnect if object is no longuer available.connect(AnyObject target, unsigned int slot)connect(AnyObject target, const std::string& slotName)connect(AnyFunction func)connect(const SignalSubscriber&)connect(qi::Signal<U>& otherSignal)

callType
– specify how to invoke subscribers. Used in combination with each subscriber’s MetaCallType to chose between synchronous and asynchronous call. The combination rule is to honor subscriber’s override, then callType, then signal’s callType and default to asynchronous