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