www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - More flexible Signals/Slots

Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Layering on top of std.signal, I've made a FlexSignal object which has 
calling rules for slots that are as flexible as normal function calls. 
  (std.signal will only accept delegates that have the _exact_ same type 
signature as the signal expects, including void return type).

In other words if it is legal to use this 'emit' command with your signal:
    sig.emit(a,b,c,d);
and it is legal to call your slot directly like this
    some_slot(a,b,c,d);

then FlexSignal allows you to connect to it:
    sig.connect(&some_slot);

Even further, FlexSignal also lets you connect anything that could be 
called in one of these ways:
    some_slot3(a,b,c);
    some_slot2(a,b);
    some_slot1(a);
    some_slot0();

It's a little heavier weight than std.signals.Signal because it has to 
create a 'thunk' for every slot added that doesn't match the signal's 
slot_t signature exactly.  But it makes for a much more flexible 
signal/slot mechanism.

This wouldn't be possible to do without the great new tuple fixes in DMD 
0.174!

Issues:

* AFAIK, there is no way to tell the difference between a class 
delegate, and a struct delegate, and a delegate literal.  Given that DMD 
can only handle class delegates, there's no way to decide currently if 
thunking is really necessary or not.  The check 
'is(slot_t==give_slot_t)' will succeed regardless of the underlying 
delegate.ptr type.  Because of this, for now FlexSignal wraps every 
delegate that comes in, regardless of whether the type signature matches.

Future/Exercise for the reader:

* It would be nice to be able to add a slot that e.g. only wants the 2nd 
  parameter emitted by the signal.
     // assume we have something we can call as 'some_slot_b(b)'
     sig.fconnect(some_slot_b, 1); // only pass argument 1

or only wants first and third args:
     // assume we have something we can call as 'some_slot_ac(a,c)'
     sig.fconnect(some_slot_ac, 0,2); // only pass arguments 0 and 2

--bb
Nov 15 2006