Signal

Full signal implementation.

It implements the emit function, for all other functionality it has this aliased to RestrictedSignal.

A signal is a way to couple components together in a very loose way. The receiver does not need to know anything about the sender and the sender does not need to know anything about the receivers. The sender will just call emit when something happens, the signal takes care of notifying all interested parties. By using wrapper delegates/functions, not even the function signature of sender/receiver need to match.

Another consequence of this very loose coupling is, that a connected object will be freed by the GC if all references to it are dropped, even if it was still connected to a signal. The connection will simply be removed. This way the developer is freed of manually keeping track of connections.

If in your application the connections made by a signal are not that loose you can use strongConnect(), in this case the GC won't free your object until it was disconnected from the signal or the signal got itself destroyed.

This struct is not thread-safe in general, it just handles the concurrent parts of the GC.

Alias This

restricted

Members

Functions

emit
void emit(Args args)

Emit the signal.

restricted
RestrictedSignal!(Args) restricted()

Get access to the rest of the signals functionality.

Bugs

The code probably won't compile with -profile because of bug: 10260

Examples

1 import std.signal;
2 import std.stdio;
3 import std.functional;
4 
5 class MyObject
6 {
7     // Public accessor method returning a RestrictedSignal, thus restricting
8     // the use of emit to this module. See the signal() string mixin below
9     // for a simpler way.
10     ref RestrictedSignal!(string, int) valueChanged() { return _valueChanged;}
11     private Signal!(string, int) _valueChanged;
12 
13     int value() @property { return _value; }
14     int value(int v) @property
15     {
16        if (v != _value)
17        {
18            _value = v;
19            // call all the connected slots with the two parameters
20            _valueChanged.emit("setting new value", v);
21        }
22        return v;
23     }
24 private:
25     int _value;
26 }
27 
28 class Observer
29 {   // our slot
30     void watch(string msg, int i)
31     {
32         writefln("Observed msg '%s' and value %s", msg, i);
33     }
34 }
35 void watch(string msg, int i)
36 {
37     writefln("Globally observed msg '%s' and value %s", msg, i);
38 }
39 void main()
40 {
41     auto a = new MyObject;
42     Observer o = new Observer;
43 
44     a.value = 3;                // should not call o.watch()
45     a.valueChanged.connect!"watch"(o);        // o.watch is the slot
46     a.value = 4;                // should call o.watch()
47     a.valueChanged.disconnect!"watch"(o);     // o.watch is no longer a slot
48     a.value = 5;                // should not call o.watch()
49     a.valueChanged.connect!"watch"(o);        // connect again
50     // Do some fancy stuff:
51     a.valueChanged.connect!Observer(o, (obj, msg, i) =>  obj.watch("Some other text I made up", i+1));
52     a.valueChanged.connect(&watch);
53     a.value = 6;                // should call o.watch()
54     destroy(o);                 // destroying o should automatically disconnect it
55     a.value = 7;                // should not call o.watch()
56 }

which should print: <pre> Observed msg 'setting new value' and value 4 Observed msg 'setting new value' and value 6 Observed msg 'Some other text I made up' and value 7 Globally observed msg 'setting new value' and value 6 Globally observed msg 'setting new value' and value 7 </pre>

Meta