qi::Signal¶
Summary¶
class qi::SignalSubscriber
Functions (class qi::SignalSubscriber)
-
qi::SignalSubscriber::signature
qi::SignalSubscriber::setCallType
qi::SignalSubscriber::SignalSubscriber
qi::SignalSubscriber::operator SignalLink
qi::SignalSubscriber::~SignalSubscriber
qi::SignalSubscriber::operator=
qi::SignalSubscriber::addActive
Members (class qi::SignalSubscriber)
-
qi::SignalSubscriber::target
qi::SignalSubscriber::executionContext
qi::SignalSubscriber::threadingModel
Signals (class qi::SignalSubscriber)
class qi::Signal
Functions (class qi::Signal)
-
qi::SignalF<T>::signature
qi::SignalBase::asyncDisconnectAll
qi::SignalBase::asyncDisconnect
Members (class qi::Signal)
Global Classes
Detailed Description¶
This is an implementation of the signal/event paradigm, with some specificities:
- Thread-safe.
- Synchronous or asynchronous subscriber invocation.
- Subscriber disconnection guarantees that subscriber is not/will not be called anymore when it returns.
- Automatic subscriber disconnection when
weak_ptr
orqi::Trackable
is used.
qi::Signal
is non-copyable.
Template arguments¶
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:
Cannot do 'clone' on YourType
Connection to a signal¶
Use Signal::connect
to register a subscriber that will be called each time
the signal is triggered.
Arguments to connect
can take multiple forms:
- A function or callable object (like
boost::function
). - A function or callable, followed by arguments and placeholders that will be bound to the function (more about that below).
- Another compatible
Signal
.
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
.
Signal::connect
returns a SignalSubscriber&
, that you can use to:
- Override the default call type for this subscriber to synchronous or
asynchronous by calling
SignalSubscriber::setCallType
(see callback type). - Obtain a subscriber identifier of type
qi::SignalLink
by casting theSignalSubscriber
:
qi::SignalLink l = someSignal.connect(callback1);
You can bind arguments directly at the connection:
void MyClass::myCallback(const std::string& str, int value) {}
qi::Signal<int> someSignal;
qi::SignalLink l = someSignal.connect(&MyClass::myCallback,
"this connection", _1);
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.
Triggering the signal¶
Triggering the signal is achieved by using the Signal::operator()
, with
arguments matching the Signal
type:
qi::Signal<int, int> sig;
// QI_EMIT is here for readability
QI_EMIT sig(51, 42);
This will invoke all subscribers with given arguments.
Signal callback type¶
It is possible to control how subscribers are invoked:
MetaCallType_Auto
is the default and means asynchronous.MetaCallType_Direct
forces a synchronous call.MetaCallType_Queued
forces an asynchronous call.
Note that if any subscriber is invoked asynchronously, the arguments passed to
Signal::operator()
will be copied.
You can set the call type of a signal globally with setCallType
, but you can
also set it per-callback. You can do that by calling setCallType
on the
SignalSubscriber
returned by connect
.
qi::SignalLink l = someSignal
.connect(callback2)
.setCallType(qi::MetaCallType_Direct);
Warning
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.
Signal lazy enabling¶
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.
void onConnect(bool c)
{
if (c)
std::cout << "First connection";
else
std::cout << "No more connections";
}
qi::Signal sig(onConnect);
qi::SignalLink l1 = sig.connect(mycallback); // calls onConnect(true)
qi::SignalLink l2 = sig.connect(mycallback); // nothing happens
sig.disconnect(l1); // nothing happens
sig.disconnect(l2); // calls onConnect(false);
Overriding signal triggering behavior (advanced)¶
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.
Reference¶
qi::Signal Class Reference¶
Introduction¶
#include <qi/signal.hpp>
Public Members¶
-
const SignalLink
invalidSignalLink
-
boost::shared_ptr<SignalBasePrivate>
_p
Public Functions¶
-
(OnSubscribers onSubscribers)Signal
-
(const Signature& signature, OnSubscribers onSubscribers)SignalBase
-
(OnSubscribers onSubscribers)SignalBase
-
()~SignalBase
-
qi::Signature
() constsignature
- template<typename F>
-
SignalSubscriber&
(const boost::function<F>& func)connect
-
SignalSubscriber&
(const SignalSubscriber& s)connect
-
SignalSubscriber&
(AnyObject object, unsigned int slot)connect
-
SignalSubscriber&
(AnyObject object, const std::string& slot)connect
-
bool
()disconnectAll
-
bool
()asyncDisconnectAll
-
bool
(const SignalLink& link)disconnect
-
bool
(const SignalLink& link)asyncDisconnect
-
void
(const GenericFunctionParameters& params, MetaCallType callType)trigger
-
void
(MetaCallType callType)setCallType
-
void
(qi::AutoAnyReference p1)operator()
-
std::vector<SignalSubscriber>
()subscribers
-
bool
()hasSubscribers
-
void
(const Signature& s)_setSignature
Types¶
- typedef detail::VoidFunctionType< P0, P1, P2, P3, P4, P5, P6, P7 >::type FunctionType¶
- typedef SignalF< FunctionType > ParentType¶
-
typedef
OnSubscribers¶qi::SignalBase::OnSubscribers
- typedef T FunctionType¶
Detailed Description¶
Class that represent an event to which function can subscribe.
Functions Documentation¶
-
qi::Signal<P0, P1, P2, P3, P4, P5, P6, P7>::
Signal
(OnSubscribers onSubscribers = OnSubscribers()¶
-
qi::SignalF<T>::
SignalF
(OnSubscribers onSubscribers = OnSubscribers()¶ Brief:
Parameters: - onSubscribers – invoked each time number of subscribers switch between 0 and 1, with argument ‘!subscribers.empty()’ Will not be called when destructor is invoked and all subscribers are removed
Signal constructor
-
qi::Signature
qi::SignalF<T>::
signature
()const
¶
-
SignalSubscriber&
qi::SignalF<T>::
connect
(...)¶ Brief:
Returns: 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)
-
qi::SignalBase::
SignalBase
(const Signature& signature, OnSubscribers onSubscribers = OnSubscribers()¶
-
qi::SignalBase::
SignalBase
(OnSubscribers onSubscribers = OnSubscribers()¶
-
qi::SignalBase::
~SignalBase
()¶
-
qi::Signature
qi::SignalBase::
signature
()const
¶
- template<typename F>
-
SignalSubscriber&
qi::SignalBase::
connect
(const boost::function<F>& func)¶
-
SignalSubscriber&
qi::SignalBase::
connect
(const SignalSubscriber& s)¶
-
SignalSubscriber&
qi::SignalBase::
connect
(AnyObject object, unsigned int slot)¶
-
SignalSubscriber&
qi::SignalBase::
connect
(AnyObject object, const std::string& slot)¶
-
bool
qi::SignalBase::
disconnectAll
()¶ Disconnect all callbacks from signal.
This function will block until all callbacks are finished.
-
bool
qi::SignalBase::
asyncDisconnectAll
()¶ Disconnect all callbacks from signal without waiting for them.
This function does not block.
-
bool
qi::SignalBase::
disconnect
(const SignalLink& link)¶ Disconnect a SignalHandler.
The associated callback will not be called anymore as soon as this function returns.
This method blocks until all the already running callbacks are finished.
-
bool
qi::SignalBase::
asyncDisconnect
(const SignalLink& link)¶ Disconnect a SignalHandler without waiting for it.
Same as disconnect, but this method does not block.
-
void
qi::SignalBase::
trigger
(const GenericFunctionParameters& params, MetaCallType callType = MetaCallType_Auto)¶ Brief:
Parameters: - params – the signal arguments
- 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
Trigger the signal with given type-erased parameters.
-
void
qi::SignalBase::
operator
(qi::AutoAnyReference p1 = qi::AutoAnyReference()¶ Trigger the signal with given arguments, and call type set by setCallType()
-
std::vector<SignalSubscriber>
qi::SignalBase::
subscribers
()¶
qi::SignalSubscriber Class Reference¶
Public Members¶
-
AnyFunction
handler
-
MetaCallType
threadingModel
-
AnyWeakObject*
target
-
unsigned int
method
-
boost::mutex
mutex
-
bool
enabled
-
std::vector<boost::thread::id>
activeThreads
-
boost::condition
inactiveThread
-
ExecutionContext*
executionContext
Public Functions¶
-
()SignalSubscriber
-
(AnyFunction func, MetaCallType callType)SignalSubscriber
-
(AnyFunction func, ExecutionContext* ec)SignalSubscriber
-
(const AnyObject& target, unsigned int method)SignalSubscriber
-
(const SignalSubscriber& b)SignalSubscriber
-
()~SignalSubscriber
-
void
(const SignalSubscriber& b)operator=
-
void
(const GenericFunctionParameters& args, MetaCallType callType)call
-
SignalSubscriber&
(MetaCallType ct)setCallType
-
void
()waitForInactive
-
void
(bool acquireLock, boost::thread::id tid)addActive
-
void
(bool acquireLock, boost::thread::id tid)removeActive
-
() constoperator SignalLink
-
Signature
() constsignature
Members Documentation¶
-
AnyFunction
qi::SignalSubscriber::
handler
¶
-
MetaCallType
qi::SignalSubscriber::
threadingModel
¶
-
AnyWeakObject*
qi::SignalSubscriber::
target
¶
-
unsigned int
qi::SignalSubscriber::
method
¶
-
boost::mutex
qi::SignalSubscriber::
mutex
¶
-
std::vector<boost::thread::id>
qi::SignalSubscriber::
activeThreads
¶
-
boost::condition
qi::SignalSubscriber::
inactiveThread
¶
-
ExecutionContext*
qi::SignalSubscriber::
executionContext
¶
Signals Documentation¶
-
SignalBase*
qi::SignalSubscriber::
source
¶
-
SignalLink
qi::SignalSubscriber::
linkId
¶ Uid that can be passed to GenericObject::disconnect()
Function Documentation¶
-
qi::SignalSubscriber::
SignalSubscriber
()¶
-
qi::SignalSubscriber::
SignalSubscriber
(AnyFunction func, MetaCallType callType = MetaCallType_Auto)¶
-
qi::SignalSubscriber::
SignalSubscriber
(AnyFunction func, ExecutionContext* ec)¶
-
qi::SignalSubscriber::
SignalSubscriber
(const AnyObject& target, unsigned int method)¶
-
qi::SignalSubscriber::
SignalSubscriber
(const SignalSubscriber& b)¶
-
qi::SignalSubscriber::
~SignalSubscriber
()¶
-
void
qi::SignalSubscriber::
call
(const GenericFunctionParameters& args, MetaCallType callType)¶ Perform the call.
Threading rules in order: Honor threadingModel if set (not auto)Honor callTypoe if set (not auto)Be asynchronous
-
SignalSubscriber&
qi::SignalSubscriber::
setCallType
(MetaCallType ct)¶
-
void
qi::SignalSubscriber::
waitForInactive
()¶ Wait until all threads are inactive except the current thread.
-
void
qi::SignalSubscriber::
addActive
(bool acquireLock, boost::thread::id tid = boost::this_thread::get_id()¶
-
void
qi::SignalSubscriber::
removeActive
(bool acquireLock, boost::thread::id tid = boost::this_thread::get_id()¶
-
qi::SignalSubscriber::
operator
SignalLink()const
¶
-
Signature
qi::SignalSubscriber::
signature
()const
¶ Brief:
Returns: the signature, or an invalid signature if extraction is impossible Try to extract exact signature of this subscriber.