#include <signal_link.hpp>
Inheritance diagram for signal_link:

| Descendant | The name of the class subclassing signal_link. | |
| Signature | The signature of the signal being sent out. |
Signals are sent using the Boost.Signals (http://www.boost.org/doc/html/signals.html) You can view the associated tutorial (http://www.boost.org/doc/html/signals/tutorial.html) to get familiar with how it works. Using signal_link as a base class for signal sending, signals can be received by any class using the operator() of the appropriate signature. Such receivers are called slots.
class SignalVoid : public signal_link<SignalVoid, void ()> { public: void Bang() { out(); // send out the void() signal when Bang is called } }; // end class SignalVoid
Signals of the same signature could be received by the following class:
class SignalVoidCounter : public boost::signals::trackable { int cnt; public: SignalVoidCounter() : cnt(0) {} void operator()() { cnt++; // whenever a void() signal is received, increase the counter } int GetCount() { return cnt; } }; // end class SignalVoidCounter
The following demonstrates how you would make a signal sender / receiver where the signal carried a float argument:
class SignalFloat : public signal_link<SignalFloat, void (float)> { float val; public: SignalFloat(float val) : val(val) {} void operator()() { out(val); // upon receiving a void() signal, send out the stored value } }; // end class SignalFloat class SignalFloatCollector : public boost::signals::trackable { optional<float> last; public: void operator()(float x) { last = x; // store the received value of the void(float) signal } optional<float> GetLast() { return last; } }; // end class SignalFloatCollector
The SignalFloat class above can also receive signals of signature void(), because it contains a void operator()() definition.
Using the above classes, it is easy to connect them together using the signal_link::operator>>=:
void simple_test() { SignalVoid banger; SignalVoidCounter counter; banger >>= counter; // this connects banger to counter banger.Bang(); // banger will now output a signal, and BOOST_CHECK(counter.GetCount() == 1); // counter will count it SignalFloat floater(2.5f); SignalFloatCollector collector; banger >>= floater >>= collector; // banger is now also connected to floater banger.Bang(); // signal from banger will now BOOST_CHECK(counter.GetCount() == 2); // increase the counter count BOOST_CHECK(collector.GetLast() == optional<float>(2.5f)); // and cause floater to output 2.5 } // end void simple_test()
void branching_test() { SignalVoid banger; SignalVoidCounter counter; SignalFloat floater(2.5f); SignalFloatCollector collector; banger >= (floater >>= collector) // floater connects to collector, banger to floater >= counter; // and banger to counter banger.Bang(); BOOST_CHECK(counter.GetCount() == 1); BOOST_CHECK(collector.GetLast() == optional<float>(2.5f)); } // end void branching_test()
void disconnect_test() { SignalVoid banger; { SignalVoidCounter counter; SignalFloat floater(2.5f); SignalFloatCollector collector; banger >= counter >= (floater >>= collector); banger.Bang(); BOOST_CHECK(counter.GetCount() == 1); BOOST_CHECK(collector.GetLast() == optional<float>(2.5f)); } // counter, floater, and collector are now gone and disconnected BOOST_CHECK(banger.default_signal().num_slots() == 0); SignalVoidCounter counter; banger >>= counter; banger.disconnect_all_slots(); banger.Bang(); BOOST_CHECK(counter.GetCount() == 0); } // end void disconnect_test
class SignalIntFloatCollector : public boost::signals::trackable { optional<int> last_int; optional<float> last_float; public: void operator()(int x) { last_int = x; } void operator()(float x) { last_float = x; } optional<int> GetLastInt() { return last_int; } optional<float> GetLastFloat() { return last_float; } }; // end class SignalIntFloatCollector
The following class, on the other hand, uses slots of different number of arguments:
class SignalMultiCollector : public boost::signals::trackable { optional<float> last, last1, last2; int cnt; public: SignalMultiCollector() : cnt(0) {} void operator()() { cnt++; } int GetCount() { return cnt; } void operator()(float val1, float val2) { last1 = val1; last2 = val2; } optional<float> GetLast1() { return last1; } optional<float> GetLast2() { return last2; } void operator()(float x) { last = x; } optional<float> GetLast() { return last; } }; // end class SignalMultiCollector
In such cases, where the operator() functions differ in their signature, standard connection operators will work out the correct connection:
void multi_type_test() { SignalVoid banger; SignalInt inter(2); SignalFloat floater(3.3f); SignalIntFloatCollector collector; banger >= (inter >>= collector) >= (floater >>= collector); banger.Bang(); BOOST_CHECK(collector.GetLastInt() == optional<int>(2)); BOOST_CHECK(collector.GetLastFloat() == optional<float>(3.3f)); } // end void multi_type_test()
class Signal2VoidCounter : public SignalVoidCounter { public: SignalVoidCounter other; }; // end class Signal2VoidCounter
Similarly, the following class could receive void() signals both through operator() and through AltInput:
class Signal2VoidInputs : public signal_link<Signal2VoidInputs, void(int)> { int result; public: Signal2VoidInputs() : result(0) {}; void operator()() { result++; out(result); } void AltInput() { result+=10; out(result); } int GetResult() { return result; } }; // end class Signal2VoidInputs
The following example shows how to connect signals to all of the above slots. For the class Signal2VoidInputs, this is accomplished using the slot_selector function:
void multi_in_test() { SignalVoid banger; Signal2VoidCounter counter; banger >= counter >= counter.other; banger.Bang(); BOOST_CHECK(counter.GetCount() == 1); BOOST_CHECK(counter.other.GetCount() == 1); Signal2VoidInputs inputs; banger >= inputs >= slot_selector<void ()> (inputs, &Signal2VoidInputs::AltInput); banger.Bang(); BOOST_CHECK(inputs.GetResult() == 11); }; // end void multi_in_test
Public Types | |
| typedef boost::signal< Signature > | default_signal_t |
Public Member Functions | |
| signal_link (const signal_link &) | |
| const default_signal_t & | default_signal () const |
| Returns the default out signal. | |
| template<typename T> | |
| Descendant & | operator>>= (T &link) |
| Connects a sequence of components using signals. | |
| template<typename T> | |
| Descendant & | operator>= (T &link) |
| Allows branching in a component connection sequence. | |
| template<typename T> | |
| Descendant & | operator>>= (slot_selector_t< T, Signature > link) |
| Allows slot functions other than operator() to be used in a sequence of components. | |
| template<typename T> | |
| Descendant & | operator>= (const slot_selector_t< T, Signature > &link) |
| Allows slot functions other than operator() to be used with branching. | |
| void | disconnect_all_slots () |
| Disconnects all slots connected to the signal_link. | |
Protected Attributes | |
| default_signal_t | out |
| Descendant& operator>>= | ( | T & | link | ) | [inline] |
Connects a sequence of components using signals.
This operator is identical to signal_link::operator>= (it connects the left component to the right component, and returns a reference to the left component), except it is evaluated right to left. This makes it semantics more suitable for connecting a chain of connections.
| Descendant& operator>= | ( | T & | link | ) | [inline] |
Allows branching in a component connection sequence.
This operator is identical to signal_link::operator>>=, (it connects the left component to the right component, and returns a reference to the left component) except it is evaluated left to right. This makes its semantics more suitable for branching connections.
| Descendant& operator>>= | ( | slot_selector_t< T, Signature > | link | ) | [inline] |
Allows slot functions other than operator() to be used in a sequence of components.
| Descendant& operator>= | ( | const slot_selector_t< T, Signature > & | link | ) | [inline] |
1.5.1-p1