signal

string mixin for creating a signal.

It creates a Signal instance named "_name", where name is given as first parameter with given protection and an accessor method with the current context protection named "name" returning either a ref RestrictedSignal or ref Signal depending on the given protection.

string
signal
@safe
(
Args...
)
(
string name
,
string protection = "private"
)

Parameters

name
Type: string

How the signal should be named. The ref returning function will be named like this, the actual struct instance will have an underscore prefixed.

protection
Type: string

Can be any valid protection specifier like "private", "protected", "package" or in addition "none". Default is "private". It specifies the protection of the Signal instance, if none is given, private is used and the ref returning function will return a Signal instead of a RestrictedSignal. The protection of the accessor method is specified by the surrounding protection scope.

Bugs

This mixin generator does not work with templated types right now because of: 10502
You might wanna use the Signal struct directly in this case. Ideally you write the code, the mixin would generate, manually to ensure an easy upgrade path when the above bug gets fixed:

ref RestrictedSignal!(SomeTemplate!int) mysig() { return _mysig;}
private Signal!(SomeTemplate!int) _mysig;

Examples

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

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