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