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