[phobos] Improving std.signals

Robert Jacques sandford at jhu.edu
Thu Sep 30 08:21:48 PDT 2010


On Wed, 29 Sep 2010 10:16:32 -0400, Johannes Pfau  
<johannespfau at googlemail.com> wrote:
>  Hi,
> I needed signals for a simple test program some time ago and because I
> wanted to learn D templates anyway I coded my own signal implementation.
> I then saw phobos already had an implementation of signals and slot in
> std.signals, but I was kinda disappointed by the implementation in
> std.signals. D offers the possibilities to enhance it in many ways.
>
> The limitations of std.signals:
> *Only supports delegates, not even functions. And it should also support
> objects/structs with opCall
> *Only supports delegates of class objects.
> The std.signal implementation attaches a DisposeEvent to the object of
> the delegate. This only works for classes. It first sounds like a good
> idea to automatically remove the delegate when the object is destroyed,
> but: explicit delete is deprecated; the garbage collector should not
> collect the object while the delegate is still registered; it limits
> delegate support to class delegates; requiring the user to explicitly
> remove the delegate is ok. Most(all?) signal implementations require
> explicitly removing the signal handlers.
> *Delegates return void. Most signal implementations have handlers return
> bool. When a handler returns false, the remaining handlers are not  
> called.
> *Uses template mixins. Template structs work as well and give a nicer
> syntax.
>
> So I merged my signals implementation with std.signals. All problems
> mentioned above have been fixed. I additionally added the following  
> things:
> *Support all handlers with void or bool return type. Using bool return
> type is preferred though, because it's faster.
> *Overloads for += and -= like in C#
>
> I also came up with a pretty nice use case for structs with opCall:
> Consider this common c# code:
> public delegate void ChangedEventHandler(object sender, EventArgs e);
> The sender object is part of the Signal type. Now, this won't work for
> D, because structs aren't objects and signals can be at module level as
> well.
> But the struct + opcall support allows us to do this in a even better  
> way:
> struct Handler
> {
>     object _sender;
>     bool opCall(string s)
>     {
>          //use _sender and s
>     }
>     this(object sender)
>     {
>         this._sender = sender;
>     }
> }
> obj.onDatareceived.connect(new Handler(obj));
>
> Using this technique we can pass any number of additional arguments.
> This could also be used to build an signal->message passing dispatcher:
> obj.onDatareceived.connect(new EventMessage!string(tid));
>
> I then looked into the glib api documentation to see what additional
> functionality it's signal handling offers.
> It's basically:
>  * Handler IDs.
> this would allow us to add the same handler to a signal multiple times.
> It also makes addafter/before easier, but it's not required for that.
> I wonder whether phobos already has something like an IDPool, something
> like this: http://ideone.com/xs80c
>  * block/unblock complete signal (easy to do)
>  * block/unblock handlers (shouldn't be too hard)
>  * threading? (Is this useful/ needed?)
>  * addafter / before (Adding handlers before a specific handler)
>  * is handler connected? (easy)
>  * stop signal emission (only useful when used with threading)
>
> If the new code was accepted into phobos, I'd offer to implement the
> features above as well, if desired.
>
> The proposed new std.signals code is located here:
> http://ideone.com/NHS5C
>

Hi Johannes,
The signals code base, as far as I know, hasn't been updated since the D1  
days, so I'm glad someone is looking at it. I can't really comment on the  
implementation itself, since I'm not a user of signals, but there is an  
API issue I'd like to point out. I consider operator overload abuse,  
particularly of the "+" for concatenation kind, verboten in D. In fact, we  
have "~" as a dedicated concatenation operator specifically to avoid this  
issue. I'd recommend changing the "+=" function to "~=" and dropping "-=".  
Also, although I don't use signals, I have used DFL's events which are  
very similar. One of my major grips about them was the inability to use  
std.algorithm, etc., to modify the underlying array of delegates. Since  
signals is really a specialized container, I would strongly recommend  
adding support for ranges and containers to it. For example, I may want to  
add my new handler before all the existing handlers, which I can't do  
currently using connect.


More information about the phobos mailing list