1 module des.arch.slot;
2 
3 import des.arch.emm;
4 
5 ///
6 package interface SignalLeverage
7 { void disconnect( SlotController ); }
8 
9 ///
10 class SlotController : ExternalMemoryManager
11 {
12     mixin EMM;
13 
14 protected:
15 
16     size_t[SignalLeverage] signals; ///
17 
18 package:
19 
20     ///
21     void connect( SignalLeverage sl )
22     in { assert( sl !is null ); }
23     body { signals[sl]++; }
24 
25     ///
26     void disconnect( SignalLeverage sl )
27     in { assert( sl !is null ); }
28     body
29     {
30         if( sl in signals )
31         {
32             if( signals[sl] > 0 ) signals[sl]--;
33             else signals.remove(sl);
34         }
35     }
36 
37 protected:
38 
39     void selfDestroy()
40     {
41         foreach( key, count; signals )
42             key.disconnect(this);
43     }
44 }
45 
46 ///
47 class Slot(Args...)
48 {
49 package:
50     ///
51     Func func;
52 
53     ///
54     SlotController control() @property { return ctrl; }
55 
56 protected:
57 
58     ///
59     SlotController ctrl;
60 
61 public:
62     alias void delegate(Args) Func; ///
63 
64     ///
65     this( SlotController ctrl, Func func )
66     in
67     {
68         assert( ctrl !is null, "slot controller must be not null" );
69         assert( func !is null, "delegate must be not null" );
70     }
71     body
72     {
73         this.ctrl = ctrl;
74         this.func = func;
75     }
76 
77     ///
78     this( SlotHandler handler, Func func )
79     { this( handler.slotController, func ); }
80 
81     ///
82     void opCall( Args args ) { func( args ); }
83 }
84 
85 ///
86 template isSlot(T)
87 {
88     enum isSlot = is( typeof( impl(T.init) ) );
89     void impl(Args...)( Slot!Args ) {}
90 }
91 
92 unittest
93 {
94     static assert(  isSlot!( Slot!string ) );
95     static assert(  isSlot!( Slot!(float,int) ) );
96     static assert( !isSlot!( string ) );
97 }
98 
99 ///
100 interface SlotHandler
101 {
102     SlotController slotController() @property;
103 }