Boost.Signals2
is not just "an array of callbacks", it has a lot of added value. IMO, the most important points are:
- Thread-safety: several threads may connect/disconnect/invoke the same signal concurrently, without introducing race conditions. This is especially useful when communicating with an asynchronous subsystem, like an Active Object running in its own thread.
connection
andscoped_connection
handles that allow disconnection without having direct access to thesignal
. Note that this is the only way to disconnect incomparable slots, likeboost::function
(orstd::function
).- Temporary slot blocking. Provides a clean way to temporarily disable a listening module (eg. when a user requests to pause receiving messages in a view).
Automatic slot lifespan tracking: a signal disconnects automatically from "expired" slots. Consider the situation when a slot is a binder referencing a non-copyable object managed by
shared_ptr
s:shared_ptr<listener> l = listener::create(); auto slot = bind(&listener::listen, l.get()); // we don't want aSignal_ to affect `listener` lifespan aSignal_.connect(your_signal_type::slot_type(slot).track(l)); // but do want to disconnect automatically when it gets destroyed
Certainly, one can re-implement all the above functionality on his own "using a vector of functions and calling each one in a loop" etc, but the question is how it would be better than Boost.Signals2
. Re-inventing the wheel is rarely a good idea.