Boost logo

Boost :

From: Cliff Green (cliffg_at_[hidden])
Date: 2005-05-13 16:05:23


I have a socket multiplexor library, with a fundamental
design question relating to Boost.Signals. My current
implementation is flawed, and I'm considering replacing
the flawed code with Boost.Signals (that is, when the
performance and multi-threading issues have been
addressed).

Consider the following pseudo-code (ignores lots of
details and is obviously not compilable - however, I do
have real working code similar to this example):

class Msg { ... };

class SocketStream {
   void sendMsg(Msg);
   // ...
};

class Multiplexor; // forward declaration

typedef boost:function<void (Msg&, Multiplexor&,
SocketStream&)> IncomingMsgCallback;

class Multiplexor {
   void registerIncomingMsgCallback (IncomingMsgCallback);
   void unregisterIncomingMsgCallback
(IncomingMsgCallback);
   // ...
};

A Multiplexor object has a container of callback
"IncomingMsgCallback") objects which are invoked whenever
an incoming message is received on a socket stream. Within
the callback, a "context" is provided (reference to the
enclosing Multiplexor object) for performance and ease of
use. (Even if this particular callback interface did not
provide a Multiplexor context, nothing would prevent the
application from storing one in the callback object
itself.) From within the callback invocation, additional
callback objects may be registered or unregistered. (This
is actually a fairly common use case - the registration of
callback functionality implements application state
machines, which are transitioned based on incoming
messages.)

The design issue is that modifying the callback container
from within the callback invocation (i.e. calling
"registerIncomingMsgCallback") requires some tricky
guarding and managing of the internal callback container.
In effect, register and unregister requests are placed on
a queue, and then applied when events (messages) are not
causing the callbacks to be invoked.

I've found that I've duplicated this code in multiple
places (primarily because there are multiple types of
callbacks - e.g. incoming msg callbacks, outgoing msg
callbacks, connection monitoring callbacks, periodic
invocation callbacks, etc). This is Not Good, and not yet)
generic.

Does Boost.Signals directly address this type of use case?
I've read the tutorial and examples many times, and it's
still not clear to me if it does (that may be due to my
understanding versus the documentation itself). Is the
trackable functionality meant to address this type of use?
If not, has this kind of usage been considered as relevant
or desirable for Signals? I'm willing to help enhance,
within the constraints of my available time.

If Boost.Signals should not support this type of usage
(i.e. modifying the signal, indirectly, from within a
connected slot), is it worthwhile to create a generic
container to support this functionality? Or are my
assumptions and approaches way off base, and I should be
considering other alternatives? (I haven't described every
possibility that I considered during design ...)

Thoughts and comments are greatly appreciated!

Cliff


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk