std.signals with multiple signals?

Bill Baxter dnewsgroup at billbaxter.com
Wed Nov 15 23:26:19 PST 2006


Serg Kovrov wrote:
> Hello, D-folks!

Howdy.

> First, my understanding of S&S:
> 
> Instance of 'emitter' class could emit predefined set of signals.

In Qt-style S&S, the signal is an object that knows how to do its own 
emitting, rather than just being some enum code and relying on an 
Emitter object.  It's just a stylistic choice, but I think it's cleaner 
than having one emitter who knows about multiple kinds of signals.

> And arbitrary class could be a 'listener', e.g. connect any of those 
> 'signals' to a it's 'slot' (arbitrary method with particular signature).

That part is the same with Qt / phobos sig&slot.

> And I expect something like this pseudo code:
> connect emitter.clicked to listener.do_something
> connect emitter.double_clicked to listener.do_something_else
> 
> With current std.signals 
> (http://digitalmars.com/d/phobos/std_signals.html) I don't get how to 
> choose signal to connect to particular slot. I mean, how to define more 
> than one signal?

Like this:
   class MyClass {
     mixin Signal!() clicked;
     mixin Signal!() dblclicked;
   };
   ...
   auto c = new MyClass;
   c.clicked.connect(&listener.do_something);
   c.dblclicked.connect(&listener.do_something_else);
   clicked.emit();
   dblclicked.emit();

Or with the signalobj.d file I posted a few messages back you can do:

   auto clicked = new SignalObj!();
   auto dlbclicked = new SignalObj!();
   clicked.connect(&listener.do_something);
   dblclicked.connect(&listener.do_something_else);
   clicked.emit();
   dblclicked.emit();

SignalObj is basically nothing more than:
   class(T...){
      mixin Signal!(T);
   }

 > Meanwhile, before std.signals and all S&S buzz, I used followed
 > (simplified, but you could see the idea) approach:
 >
 >> class Emitter
 >> {
 >>    [snip]
 >> }
 >
 > And it quite works for me, is there something wrong with it?

One thing that's missing from your simplified S&S is that your signal 
can't pass any extra information to the slots/listeners.  Your emitter 
only accepts delegates with zero arguments.  You could write a different 
Emitter that can pass some arguments, but every time you have a 
different set of arguments to pass you'd have to write a new Emitter.

The std.signal.Signal mixin automates all that.

      mixin Signal!(Widget,double) value_changed;

That one line of code basically creates an entire new customized version 
of your Emitter class tailored for passing a Widget and a double to 
listeners.

Another difference is that you haven't provided anything for 
disconnecting a listener who's no longer interested, or made any 
provisions for a listener getting destroyed.  All that is handled by 
std.signals.

Furthermore if you use the FlexSignal class I just posted a few messages 
back you will gain additional capabilities like being able to connect 
this function:

   int set_value(int v) {
      writefln("The value is: ", v);
   }

to this signal:

   FlexSignal!(int, char[]) sig;

sig.emit(5, "A message") will call set_value(5) and ignore its return 
value.  With SignalObj, or a std.signals  'mixin Signal', trying to 
connect these two will give you a variety of compile time errors, 
because a) it's a function and not a delegate, and because b) it has a 
return value, and because c) it doesn't take as many arguments as the 
Signal was expecting.

But your basic approach (make an array of delegates) is the same as what 
std.signals uses.

--bb



More information about the Digitalmars-d mailing list