annotate qt/d2/qt/Signal.d @ 279:519befd5a5d1

Fix for windows build, thanks Rainer. Fix for signals.
author eldar
date Fri, 09 Oct 2009 06:17:51 +0000
parents 5df570e79cfc
children 256ab6cb8e85
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
e78566595089 initial import
mandel
parents:
diff changeset
1 /**
e78566595089 initial import
mandel
parents:
diff changeset
2 *
e78566595089 initial import
mandel
parents:
diff changeset
3 * Copyright: Copyright QtD Team, 2008-2009
e78566595089 initial import
mandel
parents:
diff changeset
4 * Authors: Max Samukha, Eldar Insafutdinov
e78566595089 initial import
mandel
parents:
diff changeset
5 * License: <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>
e78566595089 initial import
mandel
parents:
diff changeset
6 *
e78566595089 initial import
mandel
parents:
diff changeset
7 * Copyright QtD Team, 2008-2009
e78566595089 initial import
mandel
parents:
diff changeset
8 * Distributed under the Boost Software License, Version 1.0.
e78566595089 initial import
mandel
parents:
diff changeset
9 * (See accompanying file boost-license-1.0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
e78566595089 initial import
mandel
parents:
diff changeset
10 *
e78566595089 initial import
mandel
parents:
diff changeset
11 */
16
6faf3d3cb95e CMake: implement install and package targets.
SokoL_SD
parents: 1
diff changeset
12 module qt.Signal;
1
e78566595089 initial import
mandel
parents:
diff changeset
13
e78566595089 initial import
mandel
parents:
diff changeset
14 public import qt.QGlobal;
278
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
15 public import
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
16 std.metastrings,
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
17 std.typetuple;
1
e78566595089 initial import
mandel
parents:
diff changeset
18 import core.stdc.stdlib : crealloc = realloc, cfree = free;
e78566595089 initial import
mandel
parents:
diff changeset
19 import core.stdc.string : memmove;
e78566595089 initial import
mandel
parents:
diff changeset
20 import
e78566595089 initial import
mandel
parents:
diff changeset
21 std.traits,
188
7dd099050621 initial commit for D2 support
eldar
parents: 16
diff changeset
22 core.thread,
7dd099050621 initial commit for D2 support
eldar
parents: 16
diff changeset
23 core.exception;
1
e78566595089 initial import
mandel
parents:
diff changeset
24
e78566595089 initial import
mandel
parents:
diff changeset
25 private: // private by default
e78566595089 initial import
mandel
parents:
diff changeset
26
e78566595089 initial import
mandel
parents:
diff changeset
27 alias void delegate(Object) DEvent;
e78566595089 initial import
mandel
parents:
diff changeset
28
e78566595089 initial import
mandel
parents:
diff changeset
29 extern(C) void rt_attachDisposeEvent(Object o, DEvent e);
e78566595089 initial import
mandel
parents:
diff changeset
30 extern(C) void rt_detachDisposeEvent(Object o, DEvent e);
e78566595089 initial import
mandel
parents:
diff changeset
31 extern(C) Object _d_toObject(void* p);
e78566595089 initial import
mandel
parents:
diff changeset
32
e78566595089 initial import
mandel
parents:
diff changeset
33 void realloc(T)(ref T[] a, size_t length)
e78566595089 initial import
mandel
parents:
diff changeset
34 {
e78566595089 initial import
mandel
parents:
diff changeset
35 a = (cast(T*)crealloc(a.ptr, length * T.sizeof))[0..length];
e78566595089 initial import
mandel
parents:
diff changeset
36 if (!a.ptr)
188
7dd099050621 initial commit for D2 support
eldar
parents: 16
diff changeset
37 new OutOfMemoryError(__FILE__, __LINE__);
1
e78566595089 initial import
mandel
parents:
diff changeset
38 }
e78566595089 initial import
mandel
parents:
diff changeset
39
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
40
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
41 void append(T)(ref T[] a, T element)
1
e78566595089 initial import
mandel
parents:
diff changeset
42 {
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
43 auto newLen = a.length + 1;
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
44 a = (cast(T*)crealloc(a.ptr, newLen * T.sizeof))[0..newLen];
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
45 if (!a.ptr)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
46 new OutOfMemoryError(__FILE__, __LINE__);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
47 a[newLen - 1] = element;
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
48 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
49
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
50 void move(T)(ref T[] a, size_t src, size_t dest, size_t length)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
51 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
52 if (a.length > 1)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
53 memmove(a.ptr + dest, a.ptr + src, length * T.sizeof);
1
e78566595089 initial import
mandel
parents:
diff changeset
54 }
e78566595089 initial import
mandel
parents:
diff changeset
55
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
56 // COMPILER BUG: Though this is private cannot name it 'remove' because of conflicts
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
57 // with Array.remove
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
58 void erase(T)(ref T[] a, size_t i)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
59 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
60 auto newLen = a.length - 1;
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
61 move(a, i + 1, i, newLen);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
62 realloc(a, newLen);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
63 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
64
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
65 version (QtdUnittest)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
66 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
67 unittest
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
68 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
69 int[] a;
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
70 realloc(a, 16);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
71 assert(a.length == 16);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
72 foreach (i, ref e; a)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
73 e = i;
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
74 realloc(a, 4096);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
75 assert(a.length == 4096);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
76 foreach (i, e; a[0..16])
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
77 assert(e == i);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
78 cfree(a.ptr);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
79 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
80 }
1
e78566595089 initial import
mandel
parents:
diff changeset
81
e78566595089 initial import
mandel
parents:
diff changeset
82 //TODO: should be in the standard library
e78566595089 initial import
mandel
parents:
diff changeset
83 struct STuple(A...)
e78566595089 initial import
mandel
parents:
diff changeset
84 {
e78566595089 initial import
mandel
parents:
diff changeset
85 static string genSTuple()
e78566595089 initial import
mandel
parents:
diff changeset
86 {
e78566595089 initial import
mandel
parents:
diff changeset
87 string r = "";
e78566595089 initial import
mandel
parents:
diff changeset
88 foreach (i, e; A)
e78566595089 initial import
mandel
parents:
diff changeset
89 r ~= A[i].stringof ~ " _" ~ ToString!(i) ~ ";";
e78566595089 initial import
mandel
parents:
diff changeset
90 return r;
e78566595089 initial import
mandel
parents:
diff changeset
91 }
e78566595089 initial import
mandel
parents:
diff changeset
92
e78566595089 initial import
mandel
parents:
diff changeset
93 mixin (genSTuple);
e78566595089 initial import
mandel
parents:
diff changeset
94 template at(size_t i) { mixin("alias _" ~ ToString!(i) ~ " at;"); };
e78566595089 initial import
mandel
parents:
diff changeset
95 }
e78566595089 initial import
mandel
parents:
diff changeset
96
253
073b9153ed8a Rev. 264 done right.
maxter
parents: 246
diff changeset
97 enum SignalEventId
073b9153ed8a Rev. 264 done right.
maxter
parents: 246
diff changeset
98 {
073b9153ed8a Rev. 264 done right.
maxter
parents: 246
diff changeset
99 firstSlotConnected,
073b9153ed8a Rev. 264 done right.
maxter
parents: 246
diff changeset
100 lastSlotDisconnected
073b9153ed8a Rev. 264 done right.
maxter
parents: 246
diff changeset
101 }
1
e78566595089 initial import
mandel
parents:
diff changeset
102
e78566595089 initial import
mandel
parents:
diff changeset
103 public class SignalException : Exception
e78566595089 initial import
mandel
parents:
diff changeset
104 {
e78566595089 initial import
mandel
parents:
diff changeset
105 this(string msg)
e78566595089 initial import
mandel
parents:
diff changeset
106 {
e78566595089 initial import
mandel
parents:
diff changeset
107 super(msg);
e78566595089 initial import
mandel
parents:
diff changeset
108 }
e78566595089 initial import
mandel
parents:
diff changeset
109 }
e78566595089 initial import
mandel
parents:
diff changeset
110
e78566595089 initial import
mandel
parents:
diff changeset
111 struct Fn
e78566595089 initial import
mandel
parents:
diff changeset
112 {
e78566595089 initial import
mandel
parents:
diff changeset
113 void* funcptr;
e78566595089 initial import
mandel
parents:
diff changeset
114
190
a1b48a630f73 D2 support, simple stuff works now
eldar
parents: 188
diff changeset
115 static typeof(this) opCall(R, A...)(R function(A) fn)
1
e78566595089 initial import
mandel
parents:
diff changeset
116 {
190
a1b48a630f73 D2 support, simple stuff works now
eldar
parents: 188
diff changeset
117 typeof(this) r;
1
e78566595089 initial import
mandel
parents:
diff changeset
118 r.funcptr = fn;
e78566595089 initial import
mandel
parents:
diff changeset
119 return r;
e78566595089 initial import
mandel
parents:
diff changeset
120 }
e78566595089 initial import
mandel
parents:
diff changeset
121
e78566595089 initial import
mandel
parents:
diff changeset
122 template call(R)
e78566595089 initial import
mandel
parents:
diff changeset
123 {
e78566595089 initial import
mandel
parents:
diff changeset
124 R call(A...)(A args)
e78566595089 initial import
mandel
parents:
diff changeset
125 {
e78566595089 initial import
mandel
parents:
diff changeset
126 alias R function(A) Fn;
e78566595089 initial import
mandel
parents:
diff changeset
127 return (cast(Fn)funcptr)(args);
e78566595089 initial import
mandel
parents:
diff changeset
128 }
e78566595089 initial import
mandel
parents:
diff changeset
129 }
e78566595089 initial import
mandel
parents:
diff changeset
130
e78566595089 initial import
mandel
parents:
diff changeset
131 S get(S)()
e78566595089 initial import
mandel
parents:
diff changeset
132 {
e78566595089 initial import
mandel
parents:
diff changeset
133 static assert (is(typeof(*S.init) == function));
e78566595089 initial import
mandel
parents:
diff changeset
134 return cast(S)funcptr;
e78566595089 initial import
mandel
parents:
diff changeset
135 }
e78566595089 initial import
mandel
parents:
diff changeset
136 }
e78566595089 initial import
mandel
parents:
diff changeset
137
e78566595089 initial import
mandel
parents:
diff changeset
138 struct Dg
e78566595089 initial import
mandel
parents:
diff changeset
139 {
e78566595089 initial import
mandel
parents:
diff changeset
140 void* context;
e78566595089 initial import
mandel
parents:
diff changeset
141 void* funcptr;
e78566595089 initial import
mandel
parents:
diff changeset
142
190
a1b48a630f73 D2 support, simple stuff works now
eldar
parents: 188
diff changeset
143 static typeof(this) opCall(R, A...)(R delegate(A) dg)
1
e78566595089 initial import
mandel
parents:
diff changeset
144 {
190
a1b48a630f73 D2 support, simple stuff works now
eldar
parents: 188
diff changeset
145 typeof(this) r;
1
e78566595089 initial import
mandel
parents:
diff changeset
146 r.context = dg.ptr;
e78566595089 initial import
mandel
parents:
diff changeset
147 r.funcptr = dg.funcptr;
e78566595089 initial import
mandel
parents:
diff changeset
148 return r;
e78566595089 initial import
mandel
parents:
diff changeset
149 }
e78566595089 initial import
mandel
parents:
diff changeset
150
e78566595089 initial import
mandel
parents:
diff changeset
151 template call(R)
e78566595089 initial import
mandel
parents:
diff changeset
152 {
e78566595089 initial import
mandel
parents:
diff changeset
153 R call(A...)(A args)
e78566595089 initial import
mandel
parents:
diff changeset
154 {
e78566595089 initial import
mandel
parents:
diff changeset
155 R delegate(A) dg; // BUG: parameter storage classes are ignored
e78566595089 initial import
mandel
parents:
diff changeset
156 dg.ptr = context;
e78566595089 initial import
mandel
parents:
diff changeset
157 dg.funcptr = cast(typeof(dg.funcptr))funcptr;
e78566595089 initial import
mandel
parents:
diff changeset
158 return dg(args);
e78566595089 initial import
mandel
parents:
diff changeset
159 }
e78566595089 initial import
mandel
parents:
diff changeset
160 }
e78566595089 initial import
mandel
parents:
diff changeset
161
e78566595089 initial import
mandel
parents:
diff changeset
162 S get(S)()
e78566595089 initial import
mandel
parents:
diff changeset
163 {
e78566595089 initial import
mandel
parents:
diff changeset
164 static assert (is(S == delegate));
e78566595089 initial import
mandel
parents:
diff changeset
165 S r;
e78566595089 initial import
mandel
parents:
diff changeset
166 r.ptr = context;
e78566595089 initial import
mandel
parents:
diff changeset
167 r.funcptr = cast(typeof(r.funcptr))funcptr;
e78566595089 initial import
mandel
parents:
diff changeset
168 return r;
e78566595089 initial import
mandel
parents:
diff changeset
169 }
e78566595089 initial import
mandel
parents:
diff changeset
170 }
e78566595089 initial import
mandel
parents:
diff changeset
171
e78566595089 initial import
mandel
parents:
diff changeset
172 struct Slot(R)
e78566595089 initial import
mandel
parents:
diff changeset
173 {
e78566595089 initial import
mandel
parents:
diff changeset
174 alias R Receiver;
e78566595089 initial import
mandel
parents:
diff changeset
175
e78566595089 initial import
mandel
parents:
diff changeset
176 Receiver receiver;
e78566595089 initial import
mandel
parents:
diff changeset
177 Dg invoker;
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
178 ConnectionFlags flags;
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
179
1
e78566595089 initial import
mandel
parents:
diff changeset
180 static if (is(Receiver == Dg))
e78566595089 initial import
mandel
parents:
diff changeset
181 {
e78566595089 initial import
mandel
parents:
diff changeset
182 static const isDelegate = true;
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
183
1
e78566595089 initial import
mandel
parents:
diff changeset
184 bool isDisposed()
e78566595089 initial import
mandel
parents:
diff changeset
185 {
e78566595089 initial import
mandel
parents:
diff changeset
186 return !receiver.funcptr;
e78566595089 initial import
mandel
parents:
diff changeset
187 }
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
188
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
189 void dispose()
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
190 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
191 receiver.funcptr = null;
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
192 receiver.context = null;
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
193 }
1
e78566595089 initial import
mandel
parents:
diff changeset
194
e78566595089 initial import
mandel
parents:
diff changeset
195 Object getObject()
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
196 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
197 return flags & ConnectionFlags.NoObject || !receiver.context
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
198 ? null : _d_toObject(receiver.context);
1
e78566595089 initial import
mandel
parents:
diff changeset
199 }
e78566595089 initial import
mandel
parents:
diff changeset
200 }
e78566595089 initial import
mandel
parents:
diff changeset
201 else
e78566595089 initial import
mandel
parents:
diff changeset
202 static const isDelegate = false;
e78566595089 initial import
mandel
parents:
diff changeset
203 }
e78566595089 initial import
mandel
parents:
diff changeset
204
e78566595089 initial import
mandel
parents:
diff changeset
205 enum SlotListId
e78566595089 initial import
mandel
parents:
diff changeset
206 {
e78566595089 initial import
mandel
parents:
diff changeset
207 Func, // function pointers
e78566595089 initial import
mandel
parents:
diff changeset
208 Weak, // object delegates stored in C heap
e78566595089 initial import
mandel
parents:
diff changeset
209 Strong // delegates stored in GC heap
e78566595089 initial import
mandel
parents:
diff changeset
210 }
e78566595089 initial import
mandel
parents:
diff changeset
211
e78566595089 initial import
mandel
parents:
diff changeset
212 /**
e78566595089 initial import
mandel
parents:
diff changeset
213 Used to specify the type of a signal-to-slot connection.
e78566595089 initial import
mandel
parents:
diff changeset
214
e78566595089 initial import
mandel
parents:
diff changeset
215 Examples:
e78566595089 initial import
mandel
parents:
diff changeset
216 ----
e78566595089 initial import
mandel
parents:
diff changeset
217 class Sender
e78566595089 initial import
mandel
parents:
diff changeset
218 {
e78566595089 initial import
mandel
parents:
diff changeset
219 mixin Signal!("changed");
e78566595089 initial import
mandel
parents:
diff changeset
220 void change()
e78566595089 initial import
mandel
parents:
diff changeset
221 {
e78566595089 initial import
mandel
parents:
diff changeset
222 changed.emit;
e78566595089 initial import
mandel
parents:
diff changeset
223 }
e78566595089 initial import
mandel
parents:
diff changeset
224 }
e78566595089 initial import
mandel
parents:
diff changeset
225
e78566595089 initial import
mandel
parents:
diff changeset
226
e78566595089 initial import
mandel
parents:
diff changeset
227 class Receiver
e78566595089 initial import
mandel
parents:
diff changeset
228 {
e78566595089 initial import
mandel
parents:
diff changeset
229 void alarm() {}
e78566595089 initial import
mandel
parents:
diff changeset
230 }
e78566595089 initial import
mandel
parents:
diff changeset
231
e78566595089 initial import
mandel
parents:
diff changeset
232 void main()
e78566595089 initial import
mandel
parents:
diff changeset
233 {
e78566595089 initial import
mandel
parents:
diff changeset
234 auto s = new Sender;
e78566595089 initial import
mandel
parents:
diff changeset
235 auto r = new Receiver;
e78566595089 initial import
mandel
parents:
diff changeset
236 s.changed.connect(&r.alarm); // now s weakly references r
e78566595089 initial import
mandel
parents:
diff changeset
237
e78566595089 initial import
mandel
parents:
diff changeset
238 r = null;
e78566595089 initial import
mandel
parents:
diff changeset
239 // collect garbage (assume there is no more reachable pointers
e78566595089 initial import
mandel
parents:
diff changeset
240 // to the receiver and it gets finalized)
e78566595089 initial import
mandel
parents:
diff changeset
241 ...
e78566595089 initial import
mandel
parents:
diff changeset
242
e78566595089 initial import
mandel
parents:
diff changeset
243 s.change;
e78566595089 initial import
mandel
parents:
diff changeset
244 // weak reference to the receiving object
e78566595089 initial import
mandel
parents:
diff changeset
245 // has been removed from the sender's connection lists.
e78566595089 initial import
mandel
parents:
diff changeset
246
e78566595089 initial import
mandel
parents:
diff changeset
247 r = new Receiver;
e78566595089 initial import
mandel
parents:
diff changeset
248 s.changed.connect(&r.alarm, ConnectionFlags.Strong);
e78566595089 initial import
mandel
parents:
diff changeset
249
e78566595089 initial import
mandel
parents:
diff changeset
250 r = null;
e78566595089 initial import
mandel
parents:
diff changeset
251 // collect garbage
e78566595089 initial import
mandel
parents:
diff changeset
252 ...
e78566595089 initial import
mandel
parents:
diff changeset
253 // the receiving object has not been finalized because s strongly references it.
e78566595089 initial import
mandel
parents:
diff changeset
254
e78566595089 initial import
mandel
parents:
diff changeset
255 s.change; // the receiver is called.
e78566595089 initial import
mandel
parents:
diff changeset
256 delete r;
e78566595089 initial import
mandel
parents:
diff changeset
257 s.change; // the receiver is disconnected from the sender.
e78566595089 initial import
mandel
parents:
diff changeset
258
e78566595089 initial import
mandel
parents:
diff changeset
259 static void foo()
e78566595089 initial import
mandel
parents:
diff changeset
260 {
e78566595089 initial import
mandel
parents:
diff changeset
261 }
e78566595089 initial import
mandel
parents:
diff changeset
262
e78566595089 initial import
mandel
parents:
diff changeset
263 s.changed.connect(&foo);
e78566595089 initial import
mandel
parents:
diff changeset
264 s.changed.emit; // foo is called.
e78566595089 initial import
mandel
parents:
diff changeset
265 s.changed.disconnect(&foo); // must be explicitly disconnected.
e78566595089 initial import
mandel
parents:
diff changeset
266
e78566595089 initial import
mandel
parents:
diff changeset
267 void bar()
e78566595089 initial import
mandel
parents:
diff changeset
268 {
e78566595089 initial import
mandel
parents:
diff changeset
269 }
e78566595089 initial import
mandel
parents:
diff changeset
270
e78566595089 initial import
mandel
parents:
diff changeset
271 // ConnectionFlags.NoObject must be specified for delegates
e78566595089 initial import
mandel
parents:
diff changeset
272 // to non-static local functions or struct member functions.
e78566595089 initial import
mandel
parents:
diff changeset
273 s.changed.connect(&bar, ConnectionFlags.NoObject);
e78566595089 initial import
mandel
parents:
diff changeset
274 s.changed.emit; // bar is called.
e78566595089 initial import
mandel
parents:
diff changeset
275 s.changed.disconnect(&bar); // must be explicitly disconnected.
e78566595089 initial import
mandel
parents:
diff changeset
276 }
e78566595089 initial import
mandel
parents:
diff changeset
277 ----
e78566595089 initial import
mandel
parents:
diff changeset
278 */
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
279 public enum ConnectionFlags : ubyte
1
e78566595089 initial import
mandel
parents:
diff changeset
280 {
e78566595089 initial import
mandel
parents:
diff changeset
281 ///
e78566595089 initial import
mandel
parents:
diff changeset
282 None,
e78566595089 initial import
mandel
parents:
diff changeset
283 /**
e78566595089 initial import
mandel
parents:
diff changeset
284 The receiver will be stored as weak reference (implied if ConnectionFlags.NoObject is not specified).
e78566595089 initial import
mandel
parents:
diff changeset
285 If the signal receiver is not a function pointer or a delegate referencing a D class instance.
e78566595089 initial import
mandel
parents:
diff changeset
286 the sender will not be notified when the receiving object is deleted and emitting the signal
e78566595089 initial import
mandel
parents:
diff changeset
287 connected to that receiving object will result in undefined behavior.
e78566595089 initial import
mandel
parents:
diff changeset
288 */
e78566595089 initial import
mandel
parents:
diff changeset
289 Weak = 0x0001,
e78566595089 initial import
mandel
parents:
diff changeset
290 /**
e78566595089 initial import
mandel
parents:
diff changeset
291 The receiver is stored as strong reference (implied if ConnectionFlags.NoObject is specified).
e78566595089 initial import
mandel
parents:
diff changeset
292 */
e78566595089 initial import
mandel
parents:
diff changeset
293 Strong = 0x0002,
e78566595089 initial import
mandel
parents:
diff changeset
294 /**
e78566595089 initial import
mandel
parents:
diff changeset
295 Must be specified if the receiver is not a function pointer or a delegate referencing a D class instance.
e78566595089 initial import
mandel
parents:
diff changeset
296 */
e78566595089 initial import
mandel
parents:
diff changeset
297 NoObject = 0x0004
e78566595089 initial import
mandel
parents:
diff changeset
298
e78566595089 initial import
mandel
parents:
diff changeset
299 // Queued = 0x0004,
e78566595089 initial import
mandel
parents:
diff changeset
300 // BlockingQueued = 0x0008
e78566595089 initial import
mandel
parents:
diff changeset
301 }
e78566595089 initial import
mandel
parents:
diff changeset
302
e78566595089 initial import
mandel
parents:
diff changeset
303
e78566595089 initial import
mandel
parents:
diff changeset
304 struct SlotList(SlotT, bool strong = false)
e78566595089 initial import
mandel
parents:
diff changeset
305 {
e78566595089 initial import
mandel
parents:
diff changeset
306 alias SlotT SlotType;
e78566595089 initial import
mandel
parents:
diff changeset
307 SlotType[] data;
e78566595089 initial import
mandel
parents:
diff changeset
308
e78566595089 initial import
mandel
parents:
diff changeset
309 void length(size_t length)
e78566595089 initial import
mandel
parents:
diff changeset
310 {
e78566595089 initial import
mandel
parents:
diff changeset
311 static if (strong)
e78566595089 initial import
mandel
parents:
diff changeset
312 data.length = length;
e78566595089 initial import
mandel
parents:
diff changeset
313 else
e78566595089 initial import
mandel
parents:
diff changeset
314 realloc(data, length);
e78566595089 initial import
mandel
parents:
diff changeset
315 }
e78566595089 initial import
mandel
parents:
diff changeset
316
e78566595089 initial import
mandel
parents:
diff changeset
317 SlotType* add(SlotType slot)
e78566595089 initial import
mandel
parents:
diff changeset
318 {
e78566595089 initial import
mandel
parents:
diff changeset
319 auto oldLen = data.length;
e78566595089 initial import
mandel
parents:
diff changeset
320 length = oldLen + 1;
e78566595089 initial import
mandel
parents:
diff changeset
321 auto p = &data[oldLen];
e78566595089 initial import
mandel
parents:
diff changeset
322 *p = slot;
e78566595089 initial import
mandel
parents:
diff changeset
323 return p;
e78566595089 initial import
mandel
parents:
diff changeset
324 }
e78566595089 initial import
mandel
parents:
diff changeset
325
e78566595089 initial import
mandel
parents:
diff changeset
326 SlotType* get(int slotId)
e78566595089 initial import
mandel
parents:
diff changeset
327 {
e78566595089 initial import
mandel
parents:
diff changeset
328 return &data[slotId];
e78566595089 initial import
mandel
parents:
diff changeset
329 }
e78566595089 initial import
mandel
parents:
diff changeset
330
e78566595089 initial import
mandel
parents:
diff changeset
331 void remove(int slotId)
e78566595089 initial import
mandel
parents:
diff changeset
332 {
e78566595089 initial import
mandel
parents:
diff changeset
333 move(data, slotId, slotId + 1, data.length - slotId - 1);
e78566595089 initial import
mandel
parents:
diff changeset
334 data = data[0..$ - 1];
e78566595089 initial import
mandel
parents:
diff changeset
335 }
e78566595089 initial import
mandel
parents:
diff changeset
336
e78566595089 initial import
mandel
parents:
diff changeset
337 size_t length()
e78566595089 initial import
mandel
parents:
diff changeset
338 {
e78566595089 initial import
mandel
parents:
diff changeset
339 return data.length;
e78566595089 initial import
mandel
parents:
diff changeset
340 }
e78566595089 initial import
mandel
parents:
diff changeset
341
e78566595089 initial import
mandel
parents:
diff changeset
342 void free()
e78566595089 initial import
mandel
parents:
diff changeset
343 {
e78566595089 initial import
mandel
parents:
diff changeset
344 static if (!strong)
e78566595089 initial import
mandel
parents:
diff changeset
345 cfree(data.ptr);
e78566595089 initial import
mandel
parents:
diff changeset
346 }
e78566595089 initial import
mandel
parents:
diff changeset
347 }
e78566595089 initial import
mandel
parents:
diff changeset
348
253
073b9153ed8a Rev. 264 done right.
maxter
parents: 246
diff changeset
349 public alias void delegate(int signalId, SignalEventId event) SignalEvent;
1
e78566595089 initial import
mandel
parents:
diff changeset
350
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
351 struct Receivers
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
352 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
353 struct Data
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
354 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
355 Object object;
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
356 int refs;
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
357 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
358
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
359 Data[] data;
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
360 void add(Object receiver, DEvent disposeEvent)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
361 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
362 foreach (ref d; data)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
363 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
364 if (d.object is receiver)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
365 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
366 d.refs++;
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
367 return;
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
368 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
369 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
370
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
371 append(data, Data(receiver, 1));
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
372 rt_attachDisposeEvent(receiver, disposeEvent);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
373 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
374
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
375 void remove(Object receiver, DEvent disposeEvent)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
376 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
377 foreach (i, ref d; data)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
378 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
379 if (d.object is receiver)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
380 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
381 assert (d.refs);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
382 d.refs--;
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
383 if (!d.refs)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
384 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
385 .erase(data, i);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
386 rt_detachDisposeEvent(receiver, disposeEvent);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
387 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
388 return;
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
389 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
390 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
391
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
392 assert (false);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
393 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
394
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
395 // remove all refarences for receiver, receiver has been disposed
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
396 void removeAll(Object receiver)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
397 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
398 foreach (i, ref d; data)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
399 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
400 if (d.object is receiver)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
401 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
402 .erase(data, i);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
403 return;
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
404 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
405 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
406 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
407
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
408 // remove all references for all receivers, detaching dispose events
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
409 void free(DEvent disposeEvent)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
410 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
411 foreach (i, ref d; data)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
412 rt_detachDisposeEvent(d.object, disposeEvent);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
413 cfree(data.ptr);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
414 data = null;
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
415 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
416 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
417
1
e78566595089 initial import
mandel
parents:
diff changeset
418 struct SignalConnections
e78566595089 initial import
mandel
parents:
diff changeset
419 {
e78566595089 initial import
mandel
parents:
diff changeset
420 bool isInUse;
e78566595089 initial import
mandel
parents:
diff changeset
421
e78566595089 initial import
mandel
parents:
diff changeset
422 STuple!(
e78566595089 initial import
mandel
parents:
diff changeset
423 SlotList!(Slot!(Fn)),
e78566595089 initial import
mandel
parents:
diff changeset
424 SlotList!(Slot!(Dg)),
e78566595089 initial import
mandel
parents:
diff changeset
425 SlotList!(Slot!(Dg), true)
e78566595089 initial import
mandel
parents:
diff changeset
426 ) slotLists;
e78566595089 initial import
mandel
parents:
diff changeset
427
e78566595089 initial import
mandel
parents:
diff changeset
428 STuple!(
e78566595089 initial import
mandel
parents:
diff changeset
429 Fn[],
e78566595089 initial import
mandel
parents:
diff changeset
430 Dg[]
e78566595089 initial import
mandel
parents:
diff changeset
431 ) delayedDisconnects;
e78566595089 initial import
mandel
parents:
diff changeset
432
e78566595089 initial import
mandel
parents:
diff changeset
433 void addDelayedDisconnect(Fn r)
e78566595089 initial import
mandel
parents:
diff changeset
434 {
e78566595089 initial import
mandel
parents:
diff changeset
435 delayedDisconnects.at!(0) ~= r;
e78566595089 initial import
mandel
parents:
diff changeset
436 }
e78566595089 initial import
mandel
parents:
diff changeset
437
e78566595089 initial import
mandel
parents:
diff changeset
438 void addDelayedDisconnect(Dg r)
e78566595089 initial import
mandel
parents:
diff changeset
439 {
e78566595089 initial import
mandel
parents:
diff changeset
440 delayedDisconnects.at!(1) ~= r;
e78566595089 initial import
mandel
parents:
diff changeset
441 }
e78566595089 initial import
mandel
parents:
diff changeset
442
e78566595089 initial import
mandel
parents:
diff changeset
443 SlotListType!(slotListId)* getSlotList(int slotListId)()
e78566595089 initial import
mandel
parents:
diff changeset
444 {
e78566595089 initial import
mandel
parents:
diff changeset
445 return &slotLists.tupleof[slotListId];
e78566595089 initial import
mandel
parents:
diff changeset
446 }
e78566595089 initial import
mandel
parents:
diff changeset
447
e78566595089 initial import
mandel
parents:
diff changeset
448 bool hasSlots()
e78566595089 initial import
mandel
parents:
diff changeset
449 {
e78566595089 initial import
mandel
parents:
diff changeset
450 foreach(i, e; slotLists.tupleof)
e78566595089 initial import
mandel
parents:
diff changeset
451 {
e78566595089 initial import
mandel
parents:
diff changeset
452 if (slotLists.tupleof[i].length)
e78566595089 initial import
mandel
parents:
diff changeset
453 return true;
e78566595089 initial import
mandel
parents:
diff changeset
454 }
e78566595089 initial import
mandel
parents:
diff changeset
455 return false;
e78566595089 initial import
mandel
parents:
diff changeset
456 }
e78566595089 initial import
mandel
parents:
diff changeset
457
e78566595089 initial import
mandel
parents:
diff changeset
458 int slotCount()
e78566595089 initial import
mandel
parents:
diff changeset
459 {
e78566595089 initial import
mandel
parents:
diff changeset
460 int count;
e78566595089 initial import
mandel
parents:
diff changeset
461 foreach(i, e; slotLists.tupleof)
e78566595089 initial import
mandel
parents:
diff changeset
462 count += slotLists.at!(i).length;
e78566595089 initial import
mandel
parents:
diff changeset
463 return count;
e78566595089 initial import
mandel
parents:
diff changeset
464 }
e78566595089 initial import
mandel
parents:
diff changeset
465
e78566595089 initial import
mandel
parents:
diff changeset
466 void slotListLengths(int[] lengths)
e78566595089 initial import
mandel
parents:
diff changeset
467 {
e78566595089 initial import
mandel
parents:
diff changeset
468 foreach(i, e; slotLists.tupleof)
e78566595089 initial import
mandel
parents:
diff changeset
469 lengths[i] = slotLists.at!(i).length;
e78566595089 initial import
mandel
parents:
diff changeset
470 }
e78566595089 initial import
mandel
parents:
diff changeset
471
e78566595089 initial import
mandel
parents:
diff changeset
472 SlotType!(slotListId)* addSlot(int slotListId)(SlotType!(slotListId) slot)
e78566595089 initial import
mandel
parents:
diff changeset
473 {
e78566595089 initial import
mandel
parents:
diff changeset
474 return getSlotList!(slotListId).add(slot);
e78566595089 initial import
mandel
parents:
diff changeset
475 }
e78566595089 initial import
mandel
parents:
diff changeset
476
e78566595089 initial import
mandel
parents:
diff changeset
477 void removeSlot(int slotListId)(int slotId)
e78566595089 initial import
mandel
parents:
diff changeset
478 {
e78566595089 initial import
mandel
parents:
diff changeset
479 slotLists.at!(slotListId).remove(slotId);
e78566595089 initial import
mandel
parents:
diff changeset
480 }
e78566595089 initial import
mandel
parents:
diff changeset
481
e78566595089 initial import
mandel
parents:
diff changeset
482 void free()
e78566595089 initial import
mandel
parents:
diff changeset
483 {
e78566595089 initial import
mandel
parents:
diff changeset
484 foreach(i, e; slotLists.tupleof)
e78566595089 initial import
mandel
parents:
diff changeset
485 {
e78566595089 initial import
mandel
parents:
diff changeset
486 static if (is(typeof(slotLists.at!(i).free)))
e78566595089 initial import
mandel
parents:
diff changeset
487 slotLists.at!(i).free;
e78566595089 initial import
mandel
parents:
diff changeset
488 }
e78566595089 initial import
mandel
parents:
diff changeset
489 }
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
490
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
491 void onReceiverDisposed(Object receiver)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
492 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
493 foreach (i, e; slotLists.tupleof)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
494 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
495 static if (slotLists.at!(i).SlotType.isDelegate)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
496 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
497 foreach (ref slot; slotLists.at!(i).data)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
498 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
499 if (slot.getObject is receiver)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
500 slot.dispose;
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
501 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
502 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
503 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
504 }
1
e78566595089 initial import
mandel
parents:
diff changeset
505
e78566595089 initial import
mandel
parents:
diff changeset
506 template SlotListType(int slotListId)
e78566595089 initial import
mandel
parents:
diff changeset
507 {
e78566595089 initial import
mandel
parents:
diff changeset
508 alias typeof(slotLists.tupleof)[slotListId] SlotListType;
e78566595089 initial import
mandel
parents:
diff changeset
509 }
e78566595089 initial import
mandel
parents:
diff changeset
510
e78566595089 initial import
mandel
parents:
diff changeset
511 template SlotType(int slotListId)
e78566595089 initial import
mandel
parents:
diff changeset
512 {
e78566595089 initial import
mandel
parents:
diff changeset
513 alias SlotListType!(slotListId).SlotType SlotType;
e78566595089 initial import
mandel
parents:
diff changeset
514 }
e78566595089 initial import
mandel
parents:
diff changeset
515
e78566595089 initial import
mandel
parents:
diff changeset
516 template ReceiverType(int slotListId)
e78566595089 initial import
mandel
parents:
diff changeset
517 {
e78566595089 initial import
mandel
parents:
diff changeset
518 alias SlotType!(slotListId).Receiver ReceiverType;
e78566595089 initial import
mandel
parents:
diff changeset
519 }
e78566595089 initial import
mandel
parents:
diff changeset
520
e78566595089 initial import
mandel
parents:
diff changeset
521 static const slotListCount = slotLists.tupleof.length;
e78566595089 initial import
mandel
parents:
diff changeset
522 }
e78566595089 initial import
mandel
parents:
diff changeset
523
e78566595089 initial import
mandel
parents:
diff changeset
524
268
cf6a4cd0e3f2 fix for #35
eldar
parents: 253
diff changeset
525 private Object signalSender_;
1
e78566595089 initial import
mandel
parents:
diff changeset
526
e78566595089 initial import
mandel
parents:
diff changeset
527 /**
e78566595089 initial import
mandel
parents:
diff changeset
528 If called from a slot, returns the object
e78566595089 initial import
mandel
parents:
diff changeset
529 that is emitting the signal. Otherwise, returns null.
e78566595089 initial import
mandel
parents:
diff changeset
530 */
e78566595089 initial import
mandel
parents:
diff changeset
531 public Object signalSender() {
268
cf6a4cd0e3f2 fix for #35
eldar
parents: 253
diff changeset
532 return signalSender_;
1
e78566595089 initial import
mandel
parents:
diff changeset
533 }
e78566595089 initial import
mandel
parents:
diff changeset
534
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
535 public final class SignalHandler
1
e78566595089 initial import
mandel
parents:
diff changeset
536 {
e78566595089 initial import
mandel
parents:
diff changeset
537 SignalConnections[] connections;
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
538 Receivers receivers;
1
e78566595089 initial import
mandel
parents:
diff changeset
539 Object owner;
e78566595089 initial import
mandel
parents:
diff changeset
540 int blocked;
253
073b9153ed8a Rev. 264 done right.
maxter
parents: 246
diff changeset
541
073b9153ed8a Rev. 264 done right.
maxter
parents: 246
diff changeset
542 SignalEvent signalEvent;
073b9153ed8a Rev. 264 done right.
maxter
parents: 246
diff changeset
543
1
e78566595089 initial import
mandel
parents:
diff changeset
544 alias SignalConnections.SlotType SlotType;
e78566595089 initial import
mandel
parents:
diff changeset
545 alias SignalConnections.ReceiverType ReceiverType;
e78566595089 initial import
mandel
parents:
diff changeset
546
e78566595089 initial import
mandel
parents:
diff changeset
547 public this(Object owner_) {
e78566595089 initial import
mandel
parents:
diff changeset
548 owner = owner_;
e78566595089 initial import
mandel
parents:
diff changeset
549 }
e78566595089 initial import
mandel
parents:
diff changeset
550
e78566595089 initial import
mandel
parents:
diff changeset
551 private SignalConnections* getConnections(int signalId)
e78566595089 initial import
mandel
parents:
diff changeset
552 {
e78566595089 initial import
mandel
parents:
diff changeset
553 if (signalId < connections.length)
e78566595089 initial import
mandel
parents:
diff changeset
554 return &connections[signalId];
e78566595089 initial import
mandel
parents:
diff changeset
555 return null;
e78566595089 initial import
mandel
parents:
diff changeset
556 }
e78566595089 initial import
mandel
parents:
diff changeset
557
e78566595089 initial import
mandel
parents:
diff changeset
558 private SlotType!(slotListId)* addSlot(int slotListId)(int signalId, ReceiverType!(slotListId) receiver,
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
559 Dg invoker, ConnectionFlags flags)
1
e78566595089 initial import
mandel
parents:
diff changeset
560 {
e78566595089 initial import
mandel
parents:
diff changeset
561 if (signalId >= connections.length)
e78566595089 initial import
mandel
parents:
diff changeset
562 connections.length = signalId + 1;
e78566595089 initial import
mandel
parents:
diff changeset
563 auto slot = connections[signalId].addSlot!(slotListId)(SlotType!(slotListId)(receiver, invoker));
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
564
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
565 static if (slot.isDelegate)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
566 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
567 if (!(flags & ConnectionFlags.NoObject))
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
568 receivers.add(_d_toObject(receiver.context), &onReceiverDisposed);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
569 }
1
e78566595089 initial import
mandel
parents:
diff changeset
570
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
571 if (signalEvent && connections[signalId].slotCount == 1)
253
073b9153ed8a Rev. 264 done right.
maxter
parents: 246
diff changeset
572 signalEvent(signalId, SignalEventId.firstSlotConnected);
1
e78566595089 initial import
mandel
parents:
diff changeset
573
e78566595089 initial import
mandel
parents:
diff changeset
574 return slot;
e78566595089 initial import
mandel
parents:
diff changeset
575 }
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
576
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
577 void onReceiverDisposed(Object receiver)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
578 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
579 synchronized(this)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
580 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
581 foreach(ref c; connections)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
582 c.onReceiverDisposed(receiver);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
583 receivers.removeAll(receiver);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
584 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
585 }
1
e78566595089 initial import
mandel
parents:
diff changeset
586
e78566595089 initial import
mandel
parents:
diff changeset
587 private void removeSlot(int slotListId)(int signalId, int slotId)
e78566595089 initial import
mandel
parents:
diff changeset
588 {
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
589 auto slot = connections[signalId].getSlotList!(slotListId).get(slotId);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
590 static if (slot.isDelegate)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
591 {
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
592 if (auto obj = slot.getObject)
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
593 receivers.remove(obj, &onReceiverDisposed);
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
594 }
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
595
1
e78566595089 initial import
mandel
parents:
diff changeset
596 connections[signalId].removeSlot!(slotListId)(slotId);
e78566595089 initial import
mandel
parents:
diff changeset
597
253
073b9153ed8a Rev. 264 done right.
maxter
parents: 246
diff changeset
598 if (signalEvent && !connections[signalId].slotCount)
073b9153ed8a Rev. 264 done right.
maxter
parents: 246
diff changeset
599 signalEvent(signalId, SignalEventId.lastSlotDisconnected);
1
e78566595089 initial import
mandel
parents:
diff changeset
600 }
e78566595089 initial import
mandel
parents:
diff changeset
601
e78566595089 initial import
mandel
parents:
diff changeset
602 size_t slotCount(int signalId)
e78566595089 initial import
mandel
parents:
diff changeset
603 {
e78566595089 initial import
mandel
parents:
diff changeset
604 synchronized(this)
e78566595089 initial import
mandel
parents:
diff changeset
605 {
e78566595089 initial import
mandel
parents:
diff changeset
606 auto con = getConnections(signalId);
e78566595089 initial import
mandel
parents:
diff changeset
607 if (con)
e78566595089 initial import
mandel
parents:
diff changeset
608 return con.slotCount;
e78566595089 initial import
mandel
parents:
diff changeset
609 return 0;
e78566595089 initial import
mandel
parents:
diff changeset
610 }
e78566595089 initial import
mandel
parents:
diff changeset
611 }
e78566595089 initial import
mandel
parents:
diff changeset
612
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
613 void connect(Receiver)(int signalId, Receiver receiver,
1
e78566595089 initial import
mandel
parents:
diff changeset
614 Dg invoker, ConnectionFlags flags)
e78566595089 initial import
mandel
parents:
diff changeset
615 {
e78566595089 initial import
mandel
parents:
diff changeset
616 synchronized(this)
e78566595089 initial import
mandel
parents:
diff changeset
617 {
e78566595089 initial import
mandel
parents:
diff changeset
618 static if (is(typeof(receiver.context)))
e78566595089 initial import
mandel
parents:
diff changeset
619 {
e78566595089 initial import
mandel
parents:
diff changeset
620 Object obj;
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
621 if ((flags & ConnectionFlags.NoObject))
1
e78566595089 initial import
mandel
parents:
diff changeset
622 {
e78566595089 initial import
mandel
parents:
diff changeset
623 // strong by default
e78566595089 initial import
mandel
parents:
diff changeset
624 if (flags & ConnectionFlags.Weak)
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
625 addSlot!(SlotListId.Weak)(signalId, receiver, invoker, flags);
1
e78566595089 initial import
mandel
parents:
diff changeset
626 else
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
627 addSlot!(SlotListId.Strong)(signalId, receiver, invoker, flags);
1
e78566595089 initial import
mandel
parents:
diff changeset
628 }
e78566595089 initial import
mandel
parents:
diff changeset
629 else
e78566595089 initial import
mandel
parents:
diff changeset
630 {
e78566595089 initial import
mandel
parents:
diff changeset
631 // weak by default
e78566595089 initial import
mandel
parents:
diff changeset
632 if (flags & ConnectionFlags.Strong)
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
633 addSlot!(SlotListId.Strong)(signalId, receiver, invoker, flags);
1
e78566595089 initial import
mandel
parents:
diff changeset
634 else
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
635 addSlot!(SlotListId.Weak)(signalId, receiver, invoker, flags);
1
e78566595089 initial import
mandel
parents:
diff changeset
636 }
e78566595089 initial import
mandel
parents:
diff changeset
637 }
e78566595089 initial import
mandel
parents:
diff changeset
638 else
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
639 addSlot!(SlotListId.Func)(signalId, receiver, invoker, flags);
1
e78566595089 initial import
mandel
parents:
diff changeset
640 }
e78566595089 initial import
mandel
parents:
diff changeset
641 }
e78566595089 initial import
mandel
parents:
diff changeset
642
e78566595089 initial import
mandel
parents:
diff changeset
643 void disconnect(Receiver)(int signalId, Receiver receiver)
e78566595089 initial import
mandel
parents:
diff changeset
644 {
e78566595089 initial import
mandel
parents:
diff changeset
645 synchronized(this)
e78566595089 initial import
mandel
parents:
diff changeset
646 {
e78566595089 initial import
mandel
parents:
diff changeset
647 auto cons = getConnections(signalId);
e78566595089 initial import
mandel
parents:
diff changeset
648 if (!cons)
e78566595089 initial import
mandel
parents:
diff changeset
649 return;
e78566595089 initial import
mandel
parents:
diff changeset
650
e78566595089 initial import
mandel
parents:
diff changeset
651 // if called from a slot being executed by this signal, delay disconnection
e78566595089 initial import
mandel
parents:
diff changeset
652 // until all slots has been called.
e78566595089 initial import
mandel
parents:
diff changeset
653 if (cons.isInUse)
e78566595089 initial import
mandel
parents:
diff changeset
654 {
e78566595089 initial import
mandel
parents:
diff changeset
655 cons.addDelayedDisconnect(receiver);
e78566595089 initial import
mandel
parents:
diff changeset
656 return;
e78566595089 initial import
mandel
parents:
diff changeset
657 }
e78566595089 initial import
mandel
parents:
diff changeset
658
e78566595089 initial import
mandel
parents:
diff changeset
659 TOP:
e78566595089 initial import
mandel
parents:
diff changeset
660 foreach (slotListId, e; cons.slotLists.tupleof)
e78566595089 initial import
mandel
parents:
diff changeset
661 {
e78566595089 initial import
mandel
parents:
diff changeset
662 /// COMPILER BUG: ReceiverType is evaluated to expression instead of type.
e78566595089 initial import
mandel
parents:
diff changeset
663 static if (is(typeof(cons.ReceiverType!(slotListId)) == Receiver))
e78566595089 initial import
mandel
parents:
diff changeset
664 {
e78566595089 initial import
mandel
parents:
diff changeset
665 auto slotList = cons.getSlotList!(slotListId);
e78566595089 initial import
mandel
parents:
diff changeset
666 for (int slotId; slotId < slotList.length;)
e78566595089 initial import
mandel
parents:
diff changeset
667 {
e78566595089 initial import
mandel
parents:
diff changeset
668 auto slot = slotList.get(slotId);
e78566595089 initial import
mandel
parents:
diff changeset
669 static if (slot.isDelegate)
e78566595089 initial import
mandel
parents:
diff changeset
670 {
e78566595089 initial import
mandel
parents:
diff changeset
671 if (slot.isDisposed)
e78566595089 initial import
mandel
parents:
diff changeset
672 {
e78566595089 initial import
mandel
parents:
diff changeset
673 removeSlot!(slotListId)(signalId, slotId);
e78566595089 initial import
mandel
parents:
diff changeset
674 continue;
e78566595089 initial import
mandel
parents:
diff changeset
675 }
e78566595089 initial import
mandel
parents:
diff changeset
676 }
e78566595089 initial import
mandel
parents:
diff changeset
677
e78566595089 initial import
mandel
parents:
diff changeset
678 if (slot.receiver == receiver)
e78566595089 initial import
mandel
parents:
diff changeset
679 {
e78566595089 initial import
mandel
parents:
diff changeset
680 removeSlot!(slotListId)(signalId, slotId);
e78566595089 initial import
mandel
parents:
diff changeset
681 break TOP;
e78566595089 initial import
mandel
parents:
diff changeset
682 }
e78566595089 initial import
mandel
parents:
diff changeset
683
e78566595089 initial import
mandel
parents:
diff changeset
684 slotId++;
e78566595089 initial import
mandel
parents:
diff changeset
685 }
e78566595089 initial import
mandel
parents:
diff changeset
686 }
e78566595089 initial import
mandel
parents:
diff changeset
687 }
e78566595089 initial import
mandel
parents:
diff changeset
688 }
e78566595089 initial import
mandel
parents:
diff changeset
689 }
e78566595089 initial import
mandel
parents:
diff changeset
690
e78566595089 initial import
mandel
parents:
diff changeset
691 void emit(A...)(size_t signalId, A args)
e78566595089 initial import
mandel
parents:
diff changeset
692 {
e78566595089 initial import
mandel
parents:
diff changeset
693 synchronized(this)
e78566595089 initial import
mandel
parents:
diff changeset
694 {
e78566595089 initial import
mandel
parents:
diff changeset
695 if (signalId >= connections.length || blocked)
e78566595089 initial import
mandel
parents:
diff changeset
696 return;
e78566595089 initial import
mandel
parents:
diff changeset
697 auto cons = &connections[signalId];
e78566595089 initial import
mandel
parents:
diff changeset
698
e78566595089 initial import
mandel
parents:
diff changeset
699 if (cons.hasSlots)
e78566595089 initial import
mandel
parents:
diff changeset
700 {
e78566595089 initial import
mandel
parents:
diff changeset
701 {
e78566595089 initial import
mandel
parents:
diff changeset
702 cons.isInUse = true;
268
cf6a4cd0e3f2 fix for #35
eldar
parents: 253
diff changeset
703 signalSender_ = owner;
1
e78566595089 initial import
mandel
parents:
diff changeset
704 scope(exit)
e78566595089 initial import
mandel
parents:
diff changeset
705 {
e78566595089 initial import
mandel
parents:
diff changeset
706 cons.isInUse = false;
268
cf6a4cd0e3f2 fix for #35
eldar
parents: 253
diff changeset
707 signalSender_ = null;
1
e78566595089 initial import
mandel
parents:
diff changeset
708 }
e78566595089 initial import
mandel
parents:
diff changeset
709
e78566595089 initial import
mandel
parents:
diff changeset
710 // Store the lengths to avoid calling new slots
e78566595089 initial import
mandel
parents:
diff changeset
711 // connected in the slots being called.
e78566595089 initial import
mandel
parents:
diff changeset
712 // dmd bug: int[cons.slotListCount] fails
e78566595089 initial import
mandel
parents:
diff changeset
713 static const c = cons.slotListCount;
e78566595089 initial import
mandel
parents:
diff changeset
714 int[c] lengths = void;
e78566595089 initial import
mandel
parents:
diff changeset
715 cons.slotListLengths(lengths);
e78566595089 initial import
mandel
parents:
diff changeset
716
e78566595089 initial import
mandel
parents:
diff changeset
717 foreach (slotListId, e; cons.slotLists.tupleof)
e78566595089 initial import
mandel
parents:
diff changeset
718 {
e78566595089 initial import
mandel
parents:
diff changeset
719 auto slotList = cons.getSlotList!(slotListId);
e78566595089 initial import
mandel
parents:
diff changeset
720 for (size_t slotId; slotId < lengths[slotListId];)
e78566595089 initial import
mandel
parents:
diff changeset
721 {
e78566595089 initial import
mandel
parents:
diff changeset
722 auto slot = slotList.get(slotId);
e78566595089 initial import
mandel
parents:
diff changeset
723 static if (slot.isDelegate)
e78566595089 initial import
mandel
parents:
diff changeset
724 {
e78566595089 initial import
mandel
parents:
diff changeset
725 if (slot.isDisposed)
e78566595089 initial import
mandel
parents:
diff changeset
726 {
e78566595089 initial import
mandel
parents:
diff changeset
727 removeSlot!(slotListId)(signalId, slotId);
e78566595089 initial import
mandel
parents:
diff changeset
728 lengths[slotListId]--;
e78566595089 initial import
mandel
parents:
diff changeset
729 continue;
e78566595089 initial import
mandel
parents:
diff changeset
730 }
e78566595089 initial import
mandel
parents:
diff changeset
731 }
e78566595089 initial import
mandel
parents:
diff changeset
732
e78566595089 initial import
mandel
parents:
diff changeset
733 slot.invoker.call!(void)(slot.receiver, args);
e78566595089 initial import
mandel
parents:
diff changeset
734 ++slotId;
e78566595089 initial import
mandel
parents:
diff changeset
735 }
e78566595089 initial import
mandel
parents:
diff changeset
736 }
e78566595089 initial import
mandel
parents:
diff changeset
737 }
e78566595089 initial import
mandel
parents:
diff changeset
738
e78566595089 initial import
mandel
parents:
diff changeset
739
e78566595089 initial import
mandel
parents:
diff changeset
740 // process delayed disconnects if any
e78566595089 initial import
mandel
parents:
diff changeset
741 foreach(i, e; cons.delayedDisconnects.tupleof)
e78566595089 initial import
mandel
parents:
diff changeset
742 {
e78566595089 initial import
mandel
parents:
diff changeset
743 if (cons.delayedDisconnects.at!(i).length)
e78566595089 initial import
mandel
parents:
diff changeset
744 {
e78566595089 initial import
mandel
parents:
diff changeset
745 foreach (d; cons.delayedDisconnects.at!(i))
e78566595089 initial import
mandel
parents:
diff changeset
746 disconnect(signalId, d);
e78566595089 initial import
mandel
parents:
diff changeset
747 cons.delayedDisconnects.at!(i).length = 0;
e78566595089 initial import
mandel
parents:
diff changeset
748 }
e78566595089 initial import
mandel
parents:
diff changeset
749 }
e78566595089 initial import
mandel
parents:
diff changeset
750 }
e78566595089 initial import
mandel
parents:
diff changeset
751 }
e78566595089 initial import
mandel
parents:
diff changeset
752 }
e78566595089 initial import
mandel
parents:
diff changeset
753
e78566595089 initial import
mandel
parents:
diff changeset
754 // Adjusts signal arguments and calls the slot. S - slot signature, A - signal arguments
e78566595089 initial import
mandel
parents:
diff changeset
755 private void invokeSlot(S, Receiver, A...)(Receiver r, A args)
e78566595089 initial import
mandel
parents:
diff changeset
756 {
190
a1b48a630f73 D2 support, simple stuff works now
eldar
parents: 188
diff changeset
757 r.get!(S)()(args[0..ParameterTypeTuple!(S).length]);
1
e78566595089 initial import
mandel
parents:
diff changeset
758 }
e78566595089 initial import
mandel
parents:
diff changeset
759
e78566595089 initial import
mandel
parents:
diff changeset
760 void blockSignals()
e78566595089 initial import
mandel
parents:
diff changeset
761 {
e78566595089 initial import
mandel
parents:
diff changeset
762 synchronized(this)
e78566595089 initial import
mandel
parents:
diff changeset
763 blocked++;
e78566595089 initial import
mandel
parents:
diff changeset
764 }
e78566595089 initial import
mandel
parents:
diff changeset
765
e78566595089 initial import
mandel
parents:
diff changeset
766 void unblockSignals()
e78566595089 initial import
mandel
parents:
diff changeset
767 {
e78566595089 initial import
mandel
parents:
diff changeset
768 synchronized(this)
e78566595089 initial import
mandel
parents:
diff changeset
769 {
e78566595089 initial import
mandel
parents:
diff changeset
770 if(!blocked)
e78566595089 initial import
mandel
parents:
diff changeset
771 throw new SignalException("Signals are not blocked");
e78566595089 initial import
mandel
parents:
diff changeset
772 blocked--;
e78566595089 initial import
mandel
parents:
diff changeset
773 }
e78566595089 initial import
mandel
parents:
diff changeset
774 }
e78566595089 initial import
mandel
parents:
diff changeset
775
e78566595089 initial import
mandel
parents:
diff changeset
776 ~this()
e78566595089 initial import
mandel
parents:
diff changeset
777 {
276
501128ac7a2c signals cleaned up correctly on receiver destruction
maxter
parents: 268
diff changeset
778 receivers.free(&onReceiverDisposed);
1
e78566595089 initial import
mandel
parents:
diff changeset
779 foreach(ref c; connections)
e78566595089 initial import
mandel
parents:
diff changeset
780 c.free;
e78566595089 initial import
mandel
parents:
diff changeset
781 }
e78566595089 initial import
mandel
parents:
diff changeset
782 }
e78566595089 initial import
mandel
parents:
diff changeset
783
e78566595089 initial import
mandel
parents:
diff changeset
784 //TODO: this could be avoided if named mixins didn't suck.
e78566595089 initial import
mandel
parents:
diff changeset
785 public struct SignalOps(int sigId, A...)
e78566595089 initial import
mandel
parents:
diff changeset
786 {
e78566595089 initial import
mandel
parents:
diff changeset
787 private SignalHandler sh;
e78566595089 initial import
mandel
parents:
diff changeset
788 enum { signalId = sigId }
e78566595089 initial import
mandel
parents:
diff changeset
789
e78566595089 initial import
mandel
parents:
diff changeset
790 void connect(R, B...)(R function(B) fn, ConnectionFlags flags = ConnectionFlags.None)
e78566595089 initial import
mandel
parents:
diff changeset
791 {
e78566595089 initial import
mandel
parents:
diff changeset
792 alias CheckSlot!(typeof(fn), A) check;
e78566595089 initial import
mandel
parents:
diff changeset
793 auto invoker = Dg(&sh.invokeSlot!(typeof(fn), Fn, A));
e78566595089 initial import
mandel
parents:
diff changeset
794 sh.connect(signalId, Fn(fn), invoker, flags);
e78566595089 initial import
mandel
parents:
diff changeset
795 }
e78566595089 initial import
mandel
parents:
diff changeset
796
e78566595089 initial import
mandel
parents:
diff changeset
797 void connect(R, B...)(R delegate(B) dg, ConnectionFlags flags = ConnectionFlags.None)
e78566595089 initial import
mandel
parents:
diff changeset
798 {
e78566595089 initial import
mandel
parents:
diff changeset
799 alias CheckSlot!(typeof(dg), A) check;
e78566595089 initial import
mandel
parents:
diff changeset
800 auto invoker = Dg(&sh.invokeSlot!(typeof(dg), Dg, A));
e78566595089 initial import
mandel
parents:
diff changeset
801 sh.connect(signalId, Dg(dg), invoker, flags);
e78566595089 initial import
mandel
parents:
diff changeset
802 }
e78566595089 initial import
mandel
parents:
diff changeset
803
e78566595089 initial import
mandel
parents:
diff changeset
804 void disconnect(R, B...)(R function(B) fn)
e78566595089 initial import
mandel
parents:
diff changeset
805 {
e78566595089 initial import
mandel
parents:
diff changeset
806 sh.disconnect(signalId, Fn(fn));
e78566595089 initial import
mandel
parents:
diff changeset
807 }
e78566595089 initial import
mandel
parents:
diff changeset
808
e78566595089 initial import
mandel
parents:
diff changeset
809 void disconnect(R, B...)(R delegate(B) dg)
e78566595089 initial import
mandel
parents:
diff changeset
810 {
e78566595089 initial import
mandel
parents:
diff changeset
811 sh.disconnect(signalId, Dg(dg));
e78566595089 initial import
mandel
parents:
diff changeset
812 }
e78566595089 initial import
mandel
parents:
diff changeset
813
e78566595089 initial import
mandel
parents:
diff changeset
814 void emit(A args)
e78566595089 initial import
mandel
parents:
diff changeset
815 {
e78566595089 initial import
mandel
parents:
diff changeset
816 sh.emit(signalId, args);
e78566595089 initial import
mandel
parents:
diff changeset
817 }
e78566595089 initial import
mandel
parents:
diff changeset
818
e78566595089 initial import
mandel
parents:
diff changeset
819 debug size_t slotCount()
e78566595089 initial import
mandel
parents:
diff changeset
820 {
e78566595089 initial import
mandel
parents:
diff changeset
821 return sh.slotCount(signalId);
e78566595089 initial import
mandel
parents:
diff changeset
822 }
e78566595089 initial import
mandel
parents:
diff changeset
823 }
e78566595089 initial import
mandel
parents:
diff changeset
824
e78566595089 initial import
mandel
parents:
diff changeset
825 template CheckSlot(Slot, A...)
e78566595089 initial import
mandel
parents:
diff changeset
826 {
190
a1b48a630f73 D2 support, simple stuff works now
eldar
parents: 188
diff changeset
827 static assert(ParameterTypeTuple!(Slot).length <= A.length, "Slot " ~ ParameterTypeTuple!(Slot).stringof ~
1
e78566595089 initial import
mandel
parents:
diff changeset
828 " has more prameters than signal " ~ A.stringof);
e78566595089 initial import
mandel
parents:
diff changeset
829 alias CheckSlotImpl!(Slot, 0, A) check;
e78566595089 initial import
mandel
parents:
diff changeset
830 }
e78566595089 initial import
mandel
parents:
diff changeset
831
e78566595089 initial import
mandel
parents:
diff changeset
832 template CheckSlotImpl(Slot, int i, A...)
e78566595089 initial import
mandel
parents:
diff changeset
833 {
190
a1b48a630f73 D2 support, simple stuff works now
eldar
parents: 188
diff changeset
834 alias ParameterTypeTuple!(Slot) SlotArgs;
1
e78566595089 initial import
mandel
parents:
diff changeset
835 static if (i < SlotArgs.length)
e78566595089 initial import
mandel
parents:
diff changeset
836 {
e78566595089 initial import
mandel
parents:
diff changeset
837 static assert (is(SlotArgs[i] : A[i]), "Argument " ~ ToString!(i) ~
e78566595089 initial import
mandel
parents:
diff changeset
838 ":" ~ A[i].stringof ~ " of signal " ~ A.stringof ~ " is not implicitly convertible to parameter "
278
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
839 ~ SlotArgs[i].stringof ~ " of slot " ~ SlotArgs.stringof);
1
e78566595089 initial import
mandel
parents:
diff changeset
840 alias CheckSlotImpl!(Slot, i + 1, A) next;
e78566595089 initial import
mandel
parents:
diff changeset
841 }
e78566595089 initial import
mandel
parents:
diff changeset
842 }
e78566595089 initial import
mandel
parents:
diff changeset
843
e78566595089 initial import
mandel
parents:
diff changeset
844 public template SignalHandlerOps()
e78566595089 initial import
mandel
parents:
diff changeset
845 {
e78566595089 initial import
mandel
parents:
diff changeset
846 static assert (is(typeof(this.signalHandler)),
e78566595089 initial import
mandel
parents:
diff changeset
847 "SignalHandlerOps is already instantiated in " ~ typeof(this).stringof ~ " or one of its base classes");
e78566595089 initial import
mandel
parents:
diff changeset
848
e78566595089 initial import
mandel
parents:
diff changeset
849 protected:
e78566595089 initial import
mandel
parents:
diff changeset
850 SignalHandler signalHandler_; // manages signal-to-slot connections
e78566595089 initial import
mandel
parents:
diff changeset
851
e78566595089 initial import
mandel
parents:
diff changeset
852 final SignalHandler signalHandler()
e78566595089 initial import
mandel
parents:
diff changeset
853 {
e78566595089 initial import
mandel
parents:
diff changeset
854 if (!signalHandler_)
e78566595089 initial import
mandel
parents:
diff changeset
855 {
e78566595089 initial import
mandel
parents:
diff changeset
856 signalHandler_ = new SignalHandler(this);
e78566595089 initial import
mandel
parents:
diff changeset
857 onSignalHandlerCreated(signalHandler_);
e78566595089 initial import
mandel
parents:
diff changeset
858 }
e78566595089 initial import
mandel
parents:
diff changeset
859 return signalHandler_;
e78566595089 initial import
mandel
parents:
diff changeset
860 }
e78566595089 initial import
mandel
parents:
diff changeset
861
e78566595089 initial import
mandel
parents:
diff changeset
862 void onSignalHandlerCreated(ref SignalHandler sh)
e78566595089 initial import
mandel
parents:
diff changeset
863 {
e78566595089 initial import
mandel
parents:
diff changeset
864 }
e78566595089 initial import
mandel
parents:
diff changeset
865
e78566595089 initial import
mandel
parents:
diff changeset
866 public:
e78566595089 initial import
mandel
parents:
diff changeset
867 final void blockSignals()
e78566595089 initial import
mandel
parents:
diff changeset
868 {
e78566595089 initial import
mandel
parents:
diff changeset
869 signalHandler.blockSignals();
e78566595089 initial import
mandel
parents:
diff changeset
870 }
e78566595089 initial import
mandel
parents:
diff changeset
871
e78566595089 initial import
mandel
parents:
diff changeset
872 final void unblockSignals()
e78566595089 initial import
mandel
parents:
diff changeset
873 {
e78566595089 initial import
mandel
parents:
diff changeset
874 signalHandler.unblockSignals();
e78566595089 initial import
mandel
parents:
diff changeset
875 }
278
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
876
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
877 void connect(string signalName, this T, R, B...)(R function(B) dg, ConnectionFlags flags = ConnectionFlags.None)
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
878 {
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
879 alias findSymbol!(SignalQualifier, T, signalName) sig;
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
880 alias CheckSlot!(typeof(fn), sig[2].at) check;
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
881 auto sh = signalHandler();
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
882 auto invoker = Dg(&sh.invokeSlot!(typeof(fn), Fn, sig[2].at));
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
883 sh.connect(sig[1], Fn(fn), invoker, flags);
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
884 }
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
885
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
886 void connect(string signalName, this T, R, B...)(R delegate(B) dg, ConnectionFlags flags = ConnectionFlags.None)
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
887 {
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
888 alias findSymbol!(SignalQualifier, T, signalName) sig;
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
889 alias CheckSlot!(typeof(dg), sig[2].at) check;
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
890 auto sh = signalHandler();
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
891 auto invoker = Dg(&sh.invokeSlot!(typeof(dg), Dg, sig[2].at));
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
892 sh.connect(sig[1], Dg(dg), invoker, flags);
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
893 }
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
894
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
895 void disconnect(string signalName, this T, R, B...)(R function(B) fn)
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
896 {
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
897 alias findSymbol!(SignalQualifier, T, signalName) sig;
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
898 auto sh = signalHandler();
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
899 sh.disconnect(sig[1], Fn(fn));
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
900 }
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
901
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
902 void disconnect(string signalName, this T, R, B...)(R delegate(B) dg)
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
903 {
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
904 alias findSymbol!(SignalQualifier, T, signalName) sig;
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
905 auto sh = signalHandler();
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
906 sh.disconnect(sig[1], Dg(dg));
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
907 }
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
908
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
909 debug size_t slotCount(string signalName, this T)()
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
910 {
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
911 alias findSymbol!(SignalQualifier, T, signalName) sig;
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
912 auto sh = signalHandler();
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
913 return sh.slotCount(sig[1]);
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
914 }
1
e78566595089 initial import
mandel
parents:
diff changeset
915 }
e78566595089 initial import
mandel
parents:
diff changeset
916
e78566595089 initial import
mandel
parents:
diff changeset
917 /**
278
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
918 New implementation.
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
919 */
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
920
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
921 public bool startsWith(T)(T[] source, T[] pattern)
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
922 {
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
923 return source.length >= pattern.length && source[0 .. pattern.length] == pattern[];
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
924 }
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
925
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
926 template TupleWrapper(A...) { alias A at; }
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
927
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
928 string joinArgs(A...)()
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
929 {
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
930 string res = "";
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
931 static if(A.length)
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
932 {
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
933 res = A[0].stringof;
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
934 foreach(k; A[1..$])
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
935 res ~= "," ~ k.stringof;
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
936 }
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
937 return res;
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
938 }
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
939
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
940 struct SignalQualifier
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
941 {
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
942 const string staticSymbolPrefix = "__signal";
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
943 const string name = "signal";
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
944
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
945 static bool matches(alias source, string sigName)()
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
946 {
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
947 return startsWith(source.at[0], sigName);
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
948 }
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
949 }
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
950
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
951 template staticSymbolName(Qualifier, int id)
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
952 {
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
953 const string staticSymbolName = Qualifier.staticSymbolPrefix ~ ToString!(id);
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
954 }
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
955
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
956 template signatureString(string name, A...)
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
957 {
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
958 const string signatureString = name ~ "(" ~ joinArgs!(A) ~ ")";
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
959 }
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
960
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
961 template findSymbolImpl(Qualifier, C, int id, string key)
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
962 {
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
963 static if ( is(typeof(mixin("C." ~ staticSymbolName!(Qualifier, id)))) )
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
964 {
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
965 mixin ("alias C." ~ staticSymbolName!(Qualifier, id) ~ " current;");
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
966 static if ( Qualifier.matches!(TupleWrapper!(current), key)() ) {
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
967 alias current result;
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
968 }
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
969 else
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
970 alias findSymbolImpl!(Qualifier, C, id + 1, key).result result;
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
971 }
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
972 else
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
973 {
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
974 static assert(0, Qualifier.name ~ " " ~ key ~ " not found.");
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
975 }
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
976 }
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
977
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
978 template findSymbol(Qualifier, C, string key)
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
979 {
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
980 alias findSymbolImpl!(Qualifier, C, 0, key).result findSymbol;
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
981 }
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
982
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
983 /** ---------------- */
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
984
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
985
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
986 /**
1
e78566595089 initial import
mandel
parents:
diff changeset
987 Examples:
e78566595089 initial import
mandel
parents:
diff changeset
988 ----
e78566595089 initial import
mandel
parents:
diff changeset
989 struct Args
e78566595089 initial import
mandel
parents:
diff changeset
990 {
e78566595089 initial import
mandel
parents:
diff changeset
991 bool cancel;
e78566595089 initial import
mandel
parents:
diff changeset
992 }
e78566595089 initial import
mandel
parents:
diff changeset
993
e78566595089 initial import
mandel
parents:
diff changeset
994 class C
e78566595089 initial import
mandel
parents:
diff changeset
995 {
e78566595089 initial import
mandel
parents:
diff changeset
996 private int _x;
e78566595089 initial import
mandel
parents:
diff changeset
997 // reference parameters are not supported yet,
e78566595089 initial import
mandel
parents:
diff changeset
998 // so we pass arguments by pointer.
e78566595089 initial import
mandel
parents:
diff changeset
999 mixin Signal!("xChanging", int, Args*);
e78566595089 initial import
mandel
parents:
diff changeset
1000 mixin Signal!("xChanged");
e78566595089 initial import
mandel
parents:
diff changeset
1001
e78566595089 initial import
mandel
parents:
diff changeset
1002 void x(int v)
e78566595089 initial import
mandel
parents:
diff changeset
1003 {
e78566595089 initial import
mandel
parents:
diff changeset
1004 if (v != _x)
e78566595089 initial import
mandel
parents:
diff changeset
1005 {
e78566595089 initial import
mandel
parents:
diff changeset
1006 Args args;
e78566595089 initial import
mandel
parents:
diff changeset
1007 xChanging.emit(v, &args);
e78566595089 initial import
mandel
parents:
diff changeset
1008 if (!args.cancel)
e78566595089 initial import
mandel
parents:
diff changeset
1009 {
e78566595089 initial import
mandel
parents:
diff changeset
1010 _x = v;
e78566595089 initial import
mandel
parents:
diff changeset
1011 xChanged.emit;
e78566595089 initial import
mandel
parents:
diff changeset
1012 }
e78566595089 initial import
mandel
parents:
diff changeset
1013 }
e78566595089 initial import
mandel
parents:
diff changeset
1014 }
e78566595089 initial import
mandel
parents:
diff changeset
1015 }
e78566595089 initial import
mandel
parents:
diff changeset
1016 ----
e78566595089 initial import
mandel
parents:
diff changeset
1017 */
e78566595089 initial import
mandel
parents:
diff changeset
1018 template Signal(string name, A...)
e78566595089 initial import
mandel
parents:
diff changeset
1019 {
e78566595089 initial import
mandel
parents:
diff changeset
1020 mixin SignalImpl!(0, name, A);
e78566595089 initial import
mandel
parents:
diff changeset
1021 }
e78566595089 initial import
mandel
parents:
diff changeset
1022
e78566595089 initial import
mandel
parents:
diff changeset
1023 template SignalImpl(int index, string name, A...)
e78566595089 initial import
mandel
parents:
diff changeset
1024 {
e78566595089 initial import
mandel
parents:
diff changeset
1025 static if (is(typeof(mixin(typeof(this).stringof ~ ".__sig" ~ ToString!(index)))))
e78566595089 initial import
mandel
parents:
diff changeset
1026 mixin SignalImpl!(index + 1, name, A);
e78566595089 initial import
mandel
parents:
diff changeset
1027 else
e78566595089 initial import
mandel
parents:
diff changeset
1028 {
e78566595089 initial import
mandel
parents:
diff changeset
1029 // mixed-in once
e78566595089 initial import
mandel
parents:
diff changeset
1030 static if (!is(typeof(this.signalHandler)))
e78566595089 initial import
mandel
parents:
diff changeset
1031 {
e78566595089 initial import
mandel
parents:
diff changeset
1032 mixin SignalHandlerOps;
e78566595089 initial import
mandel
parents:
diff changeset
1033 }
278
5df570e79cfc new syntax for connecting using static information
eldar
parents: 276
diff changeset
1034 /* deprecated */ mixin("private static const int __sig" ~ ToString!(index) ~ " = " ~ ToString!(index) ~ ";");
279
519befd5a5d1 Fix for windows build, thanks Rainer.
eldar
parents: 278
diff changeset
1035 // mixin("public alias TypeTuple!(\"" ~ signatureString!(name, A) ~ "\", index, TupleWrapper!(A)) __signal" ~ ToString!(index) ~ ";");
1
e78566595089 initial import
mandel
parents:
diff changeset
1036 mixin("SignalOps!(" ~ ToString!(index) ~ ", A) " ~ name ~ "(){ return SignalOps!("
e78566595089 initial import
mandel
parents:
diff changeset
1037 ~ ToString!(index) ~ ", A)(signalHandler); }");
e78566595089 initial import
mandel
parents:
diff changeset
1038 }
e78566595089 initial import
mandel
parents:
diff changeset
1039 }
e78566595089 initial import
mandel
parents:
diff changeset
1040
e78566595089 initial import
mandel
parents:
diff changeset
1041 extern(C) alias void function(void*) SlotConnector;
e78566595089 initial import
mandel
parents:
diff changeset
1042
e78566595089 initial import
mandel
parents:
diff changeset
1043 debug (UnitTest)
e78566595089 initial import
mandel
parents:
diff changeset
1044 {
e78566595089 initial import
mandel
parents:
diff changeset
1045 class A
e78566595089 initial import
mandel
parents:
diff changeset
1046 {
e78566595089 initial import
mandel
parents:
diff changeset
1047 mixin Signal!("scorched", int);
e78566595089 initial import
mandel
parents:
diff changeset
1048
e78566595089 initial import
mandel
parents:
diff changeset
1049 int signalId1 = -1;
e78566595089 initial import
mandel
parents:
diff changeset
1050 int signalId2 = -1;
e78566595089 initial import
mandel
parents:
diff changeset
1051
e78566595089 initial import
mandel
parents:
diff changeset
1052 void onFirstConnect(int sId)
e78566595089 initial import
mandel
parents:
diff changeset
1053 {
e78566595089 initial import
mandel
parents:
diff changeset
1054 signalId1 = sId;
e78566595089 initial import
mandel
parents:
diff changeset
1055 }
e78566595089 initial import
mandel
parents:
diff changeset
1056
e78566595089 initial import
mandel
parents:
diff changeset
1057 void onLastDisconnect(int sId)
e78566595089 initial import
mandel
parents:
diff changeset
1058 {
e78566595089 initial import
mandel
parents:
diff changeset
1059 signalId2 = sId;
e78566595089 initial import
mandel
parents:
diff changeset
1060 }
e78566595089 initial import
mandel
parents:
diff changeset
1061
e78566595089 initial import
mandel
parents:
diff changeset
1062 this()
e78566595089 initial import
mandel
parents:
diff changeset
1063 {
e78566595089 initial import
mandel
parents:
diff changeset
1064 signalHandler.firstSlotConnected = &onFirstConnect;
e78566595089 initial import
mandel
parents:
diff changeset
1065 signalHandler.lastSlotDisconnected = &onLastDisconnect;
e78566595089 initial import
mandel
parents:
diff changeset
1066 }
e78566595089 initial import
mandel
parents:
diff changeset
1067 }
e78566595089 initial import
mandel
parents:
diff changeset
1068
e78566595089 initial import
mandel
parents:
diff changeset
1069 class B : A
e78566595089 initial import
mandel
parents:
diff changeset
1070 {
e78566595089 initial import
mandel
parents:
diff changeset
1071 mixin Signal!("booed", int);
e78566595089 initial import
mandel
parents:
diff changeset
1072
e78566595089 initial import
mandel
parents:
diff changeset
1073 int bazSum;
e78566595089 initial import
mandel
parents:
diff changeset
1074 void baz(int i)
e78566595089 initial import
mandel
parents:
diff changeset
1075 {
e78566595089 initial import
mandel
parents:
diff changeset
1076 bazSum += i;
e78566595089 initial import
mandel
parents:
diff changeset
1077 }
e78566595089 initial import
mandel
parents:
diff changeset
1078 }
e78566595089 initial import
mandel
parents:
diff changeset
1079
e78566595089 initial import
mandel
parents:
diff changeset
1080 class C : A
e78566595089 initial import
mandel
parents:
diff changeset
1081 {
e78566595089 initial import
mandel
parents:
diff changeset
1082 mixin Signal!("cooked");
e78566595089 initial import
mandel
parents:
diff changeset
1083 }
e78566595089 initial import
mandel
parents:
diff changeset
1084 }
e78566595089 initial import
mandel
parents:
diff changeset
1085
e78566595089 initial import
mandel
parents:
diff changeset
1086 unittest
e78566595089 initial import
mandel
parents:
diff changeset
1087 {
e78566595089 initial import
mandel
parents:
diff changeset
1088 static int fooSum;
e78566595089 initial import
mandel
parents:
diff changeset
1089 static int barSum;
e78566595089 initial import
mandel
parents:
diff changeset
1090
e78566595089 initial import
mandel
parents:
diff changeset
1091 static void foo(int i)
e78566595089 initial import
mandel
parents:
diff changeset
1092 {
e78566595089 initial import
mandel
parents:
diff changeset
1093 fooSum += i;
e78566595089 initial import
mandel
parents:
diff changeset
1094 }
e78566595089 initial import
mandel
parents:
diff changeset
1095
e78566595089 initial import
mandel
parents:
diff changeset
1096 void bar(long i)
e78566595089 initial import
mandel
parents:
diff changeset
1097 {
e78566595089 initial import
mandel
parents:
diff changeset
1098 barSum += i;
e78566595089 initial import
mandel
parents:
diff changeset
1099 }
e78566595089 initial import
mandel
parents:
diff changeset
1100
e78566595089 initial import
mandel
parents:
diff changeset
1101 auto a = new A;
e78566595089 initial import
mandel
parents:
diff changeset
1102 auto b = new B;
e78566595089 initial import
mandel
parents:
diff changeset
1103 auto c = new C;
e78566595089 initial import
mandel
parents:
diff changeset
1104 assert(b.scorched.signalId == 0);
e78566595089 initial import
mandel
parents:
diff changeset
1105 assert(b.booed.signalId == 1);
e78566595089 initial import
mandel
parents:
diff changeset
1106 assert(c.cooked.signalId == 1);
e78566595089 initial import
mandel
parents:
diff changeset
1107
e78566595089 initial import
mandel
parents:
diff changeset
1108 auto sh = b.signalHandler;
e78566595089 initial import
mandel
parents:
diff changeset
1109
e78566595089 initial import
mandel
parents:
diff changeset
1110 b.scorched.connect(&foo);
e78566595089 initial import
mandel
parents:
diff changeset
1111 assert(sh.connections.length == 1);
e78566595089 initial import
mandel
parents:
diff changeset
1112 assert(b.signalId1 == 0);
e78566595089 initial import
mandel
parents:
diff changeset
1113 auto scCons = &sh.connections[0];
e78566595089 initial import
mandel
parents:
diff changeset
1114
e78566595089 initial import
mandel
parents:
diff changeset
1115 assert(scCons.getSlotList!(SlotListId.Func).length == 1);
e78566595089 initial import
mandel
parents:
diff changeset
1116 b.scorched.emit(1);
e78566595089 initial import
mandel
parents:
diff changeset
1117 assert(fooSum == 1);
e78566595089 initial import
mandel
parents:
diff changeset
1118
e78566595089 initial import
mandel
parents:
diff changeset
1119 b.scorched.connect(&bar, ConnectionFlags.NoObject);
e78566595089 initial import
mandel
parents:
diff changeset
1120 assert(sh.connections.length == 1);
e78566595089 initial import
mandel
parents:
diff changeset
1121 assert(scCons.getSlotList!(SlotListId.Strong).length == 1);
e78566595089 initial import
mandel
parents:
diff changeset
1122 b.scorched.emit(1);
e78566595089 initial import
mandel
parents:
diff changeset
1123 assert (fooSum == 2 && barSum == 1);
e78566595089 initial import
mandel
parents:
diff changeset
1124
e78566595089 initial import
mandel
parents:
diff changeset
1125 b.scorched.connect(&b.baz);
e78566595089 initial import
mandel
parents:
diff changeset
1126 assert(scCons.getSlotList!(SlotListId.Weak).length == 1);
e78566595089 initial import
mandel
parents:
diff changeset
1127 b.scorched.emit(1);
e78566595089 initial import
mandel
parents:
diff changeset
1128 assert (fooSum == 3 && barSum == 2 && b.bazSum == 1);
e78566595089 initial import
mandel
parents:
diff changeset
1129
e78566595089 initial import
mandel
parents:
diff changeset
1130 b.scorched.disconnect(&bar);
e78566595089 initial import
mandel
parents:
diff changeset
1131 assert(scCons.slotCount == 2);
e78566595089 initial import
mandel
parents:
diff changeset
1132 b.scorched.disconnect(&b.baz);
e78566595089 initial import
mandel
parents:
diff changeset
1133 assert(scCons.slotCount == 1);
e78566595089 initial import
mandel
parents:
diff changeset
1134 b.scorched.disconnect(&foo);
e78566595089 initial import
mandel
parents:
diff changeset
1135 assert(scCons.slotCount == 0);
e78566595089 initial import
mandel
parents:
diff changeset
1136 assert(b.signalId2 == 0);
e78566595089 initial import
mandel
parents:
diff changeset
1137
e78566595089 initial import
mandel
parents:
diff changeset
1138 fooSum = 0;
e78566595089 initial import
mandel
parents:
diff changeset
1139 void connectFoo()
e78566595089 initial import
mandel
parents:
diff changeset
1140 {
e78566595089 initial import
mandel
parents:
diff changeset
1141 b.scorched.connect(&foo);
e78566595089 initial import
mandel
parents:
diff changeset
1142 b.scorched.disconnect(&connectFoo);
e78566595089 initial import
mandel
parents:
diff changeset
1143 }
e78566595089 initial import
mandel
parents:
diff changeset
1144
e78566595089 initial import
mandel
parents:
diff changeset
1145 b.scorched.connect(&connectFoo, ConnectionFlags.NoObject);
e78566595089 initial import
mandel
parents:
diff changeset
1146 b.scorched.emit(1);
e78566595089 initial import
mandel
parents:
diff changeset
1147 assert(scCons.getSlotList!(SlotListId.Func).length == 1);
e78566595089 initial import
mandel
parents:
diff changeset
1148 assert(scCons.getSlotList!(SlotListId.Strong).length == 0);
e78566595089 initial import
mandel
parents:
diff changeset
1149 assert(!fooSum);
e78566595089 initial import
mandel
parents:
diff changeset
1150
e78566595089 initial import
mandel
parents:
diff changeset
1151 auto r = new B();
e78566595089 initial import
mandel
parents:
diff changeset
1152 b.scorched.connect(&r.baz);
e78566595089 initial import
mandel
parents:
diff changeset
1153 assert(scCons.getSlotList!(SlotListId.Weak).length == 1);
e78566595089 initial import
mandel
parents:
diff changeset
1154 b.scorched.emit(1);
e78566595089 initial import
mandel
parents:
diff changeset
1155 assert(r.bazSum == 1);
e78566595089 initial import
mandel
parents:
diff changeset
1156 assert(fooSum == 1);
e78566595089 initial import
mandel
parents:
diff changeset
1157
e78566595089 initial import
mandel
parents:
diff changeset
1158 delete(r);
e78566595089 initial import
mandel
parents:
diff changeset
1159 assert(scCons.getSlotList!(SlotListId.Weak).length == 1);
e78566595089 initial import
mandel
parents:
diff changeset
1160 b.scorched.emit(1);
e78566595089 initial import
mandel
parents:
diff changeset
1161 assert(scCons.getSlotList!(SlotListId.Weak).length == 0);
e78566595089 initial import
mandel
parents:
diff changeset
1162 }