Mercurial > projects > qtd
annotate qt/d1/qt/Signal.d @ 286:e6d48cb9d1e0 signals2
(none)
author | eldar |
---|---|
date | Sun, 08 Nov 2009 19:19:09 +0000 |
parents | 1f6923c8cba0 |
children |
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 public template SignalHandlerOps() | |
821 { | |
822 static assert (is(typeof(this.signalHandler)), | |
823 "SignalHandlerOps is already instantiated in " ~ typeof(this).stringof ~ " or one of its base classes"); | |
824 | |
825 protected: | |
826 SignalHandler signalHandler_; // manages signal-to-slot connections | |
827 | |
828 final SignalHandler signalHandler() | |
829 { | |
830 if (!signalHandler_) | |
831 { | |
832 signalHandler_ = new SignalHandler(this); | |
833 onSignalHandlerCreated(signalHandler_); | |
834 } | |
835 return signalHandler_; | |
836 } | |
837 | |
838 void onSignalHandlerCreated(ref SignalHandler sh) | |
839 { | |
840 } | |
841 | |
842 public: | |
843 final void blockSignals() | |
844 { | |
845 signalHandler.blockSignals(); | |
846 } | |
847 | |
848 final void unblockSignals() | |
849 { | |
850 signalHandler.unblockSignals(); | |
851 } | |
278 | 852 |
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
|
853 template connect(string signalName, A...) |
278 | 854 { |
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
|
855 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
|
856 { |
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
|
857 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
|
858 { |
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
|
859 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
|
860 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
|
861 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
|
862 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
|
863 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
|
864 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
|
865 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
|
866 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
|
867 } |
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
|
868 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
|
869 { |
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
|
870 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
|
871 } |
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
|
872 } |
278 | 873 } |
874 | |
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
|
875 template disconnect(string signalName, A...) |
278 | 876 { |
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
|
877 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
|
878 { |
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
|
879 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
|
880 { |
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
|
881 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
|
882 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
|
883 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
|
884 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
|
885 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
|
886 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
|
887 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
|
888 } |
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
|
889 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
|
890 { |
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
|
891 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
|
892 } |
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
|
893 } |
278 | 894 } |
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
|
895 /* |
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 template slotCount(string signalName, A...) |
278 | 897 { |
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
|
898 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
|
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 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
|
903 } |
278 | 904 } |
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
|
905 */ |
1 | 906 } |
907 | |
908 /** | |
278 | 909 New implementation. |
910 */ | |
911 | |
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
|
912 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
|
913 |
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
|
914 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
|
915 |
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 isDg(Dg) |
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 enum { isDg = is(Dg == delegate) } |
278 | 919 } |
920 | |
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
|
921 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
|
922 { |
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 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
|
924 } |
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 |
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 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
|
927 { |
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 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
|
929 } |
278 | 930 |
931 string joinArgs(A...)() | |
932 { | |
933 string res = ""; | |
934 static if(A.length) | |
935 { | |
936 res = A[0].stringof; | |
937 foreach(k; A[1..$]) | |
938 res ~= "," ~ k.stringof; | |
939 } | |
940 return res; | |
941 } | |
942 | |
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
|
943 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
|
944 { |
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
|
945 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
|
946 } |
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
|
947 |
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
|
948 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
|
949 { |
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
|
950 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
|
951 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
|
952 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
|
953 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
|
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 |
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 template SignalPred(T1, T2) |
278 | 957 { |
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
|
958 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
|
959 } |
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
|
960 |
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
|
961 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
|
962 { |
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 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
|
964 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
|
965 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
|
966 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
|
967 } |
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 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
|
970 { |
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
|
971 static if (i < Needle.at.length) |
278 | 972 { |
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
|
973 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
|
974 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
|
975 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
|
976 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
|
977 } |
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
|
978 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
|
979 { |
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
|
980 enum { value = true } |
278 | 981 } |
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 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
|
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 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
|
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 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
|
989 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
|
990 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
|
991 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
|
992 } |
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 } |
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 |
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 template SigBySignPred(string name, SigArgs...) |
278 | 996 { |
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
|
997 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
|
998 { |
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 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
|
1000 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
|
1001 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
|
1002 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
|
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 } |
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 |
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 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
|
1007 { |
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 const string staticSymbolName = prefix ~ ToString!(id); |
278 | 1009 } |
1010 | |
1011 template signatureString(string name, A...) | |
1012 { | |
1013 const string signatureString = name ~ "(" ~ joinArgs!(A) ~ ")"; | |
1014 } | |
1015 | |
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
|
1016 template findSymbolImpl(string prefix, C, int id, alias pred) |
278 | 1017 { |
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
|
1018 static if ( is(typeof(mixin("C." ~ staticSymbolName!(prefix, id)))) ) |
278 | 1019 { |
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
|
1020 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
|
1021 static if (pred!(current)) |
278 | 1022 alias current result; |
1023 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
|
1024 alias findSymbolImpl!(prefix, C, id + 1, pred).result result; |
278 | 1025 } |
1026 else | |
1027 { | |
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
|
1028 alias void result; |
278 | 1029 } |
1030 } | |
1031 | |
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
|
1032 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
|
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 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
|
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 |
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
|
1037 template findSignal(C, string name, Receiver, SigArgs...) |
278 | 1038 { |
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
|
1039 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
|
1040 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
|
1041 { |
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 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
|
1043 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
|
1044 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
|
1045 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
|
1046 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
|
1047 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
|
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 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
|
1050 { |
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
|
1051 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
|
1052 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
|
1053 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
|
1054 } |
278 | 1055 } |
1056 | |
1057 | |
284 | 1058 public string SignalEmitter(A...)(SignalType signalType, string name, int index) |
1059 { | |
1060 string fullArgs, args; | |
1061 static if (A.length) | |
1062 { | |
1063 fullArgs = A[0].stringof ~ " a0"; | |
1064 args = ", a0"; | |
1065 foreach(i, _; A[1..$]) | |
1066 { | |
1067 fullArgs ~= ", " ~ A[i+1].stringof ~ " a" ~ __toString(i+1); | |
1068 args ~= ", a" ~ __toString(i+1); | |
1069 } | |
1070 } | |
1071 string attribute; | |
1072 string sigName = name; | |
1073 if (signalType == SignalType.BindQtSignal) | |
1074 name ~= "_emit"; | |
1075 else | |
1076 attribute = "protected "; | |
1077 string str = attribute ~ "void " ~ name ~ "(" ~ fullArgs ~ ")" ~ | |
1078 "{ this.signalHandler.emit(" ~ __toString(index) ~ args ~ "); }"; | |
1079 return str; | |
1080 } | |
1081 | |
278 | 1082 /** |
1 | 1083 Examples: |
1084 ---- | |
1085 struct Args | |
1086 { | |
1087 bool cancel; | |
1088 } | |
1089 | |
1090 class C | |
1091 { | |
1092 private int _x; | |
1093 // reference parameters are not supported yet, | |
1094 // so we pass arguments by pointer. | |
1095 mixin Signal!("xChanging", int, Args*); | |
1096 mixin Signal!("xChanged"); | |
1097 | |
1098 void x(int v) | |
1099 { | |
1100 if (v != _x) | |
1101 { | |
1102 Args args; | |
1103 xChanging.emit(v, &args); | |
1104 if (!args.cancel) | |
1105 { | |
1106 _x = v; | |
1107 xChanged.emit; | |
1108 } | |
1109 } | |
1110 } | |
1111 } | |
1112 ---- | |
1113 */ | |
284 | 1114 |
1115 enum SignalType | |
1 | 1116 { |
284 | 1117 BindQtSignal, |
1118 NewSignal | |
1 | 1119 } |
1120 | |
284 | 1121 template BindQtSignal(string name, A...) |
1122 { | |
1123 mixin SignalImpl!(0, name, SignalType.BindQtSignal, A); | |
1124 } | |
1125 | |
1126 template Signal(string name, A...) | |
1127 { | |
1128 mixin SignalImpl!(0, name, SignalType.NewSignal, A); | |
1129 } | |
1130 | |
1131 template SignalImpl(int index, string name, SignalType signalType, A...) | |
1 | 1132 { |
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
|
1133 static if (is(typeof(mixin(typeof(this).stringof ~ ".__signal" ~ ToString!(index))))) |
284 | 1134 mixin SignalImpl!(index + 1, name, signalType, A); |
1 | 1135 else |
1136 { | |
1137 // mixed-in once | |
1138 static if (!is(typeof(this.signalHandler))) | |
1139 mixin SignalHandlerOps; | |
284 | 1140 |
1141 mixin (SignalEmitter!(A)(signalType, name, index)); | |
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
|
1142 mixin("public alias Tuple!(\"" ~ name ~ "\", index, A) __signal" ~ ToString!(index) ~ ";"); |
1 | 1143 } |
1144 } | |
1145 | |
1146 extern(C) alias void function(void*) SlotConnector; | |
1147 | |
1148 debug (UnitTest) | |
1149 { | |
1150 class A | |
1151 { | |
1152 mixin Signal!("scorched", int); | |
1153 | |
1154 int signalId1 = -1; | |
1155 int signalId2 = -1; | |
1156 | |
1157 void onFirstConnect(int sId) | |
1158 { | |
1159 signalId1 = sId; | |
1160 } | |
1161 | |
1162 void onLastDisconnect(int sId) | |
1163 { | |
1164 signalId2 = sId; | |
1165 } | |
1166 | |
1167 this() | |
1168 { | |
1169 signalHandler.firstSlotConnected = &onFirstConnect; | |
1170 signalHandler.lastSlotDisconnected = &onLastDisconnect; | |
1171 } | |
1172 } | |
1173 | |
1174 class B : A | |
1175 { | |
1176 mixin Signal!("booed", int); | |
1177 | |
1178 int bazSum; | |
1179 void baz(int i) | |
1180 { | |
1181 bazSum += i; | |
1182 } | |
1183 } | |
1184 | |
1185 class C : A | |
1186 { | |
1187 mixin Signal!("cooked"); | |
1188 } | |
1189 } | |
1190 | |
1191 unittest | |
1192 { | |
1193 static int fooSum; | |
1194 static int barSum; | |
1195 | |
1196 static void foo(int i) | |
1197 { | |
1198 fooSum += i; | |
1199 } | |
1200 | |
1201 void bar(long i) | |
1202 { | |
1203 barSum += i; | |
1204 } | |
1205 | |
1206 auto a = new A; | |
1207 auto b = new B; | |
1208 auto c = new C; | |
1209 assert(b.scorched.signalId == 0); | |
1210 assert(b.booed.signalId == 1); | |
1211 assert(c.cooked.signalId == 1); | |
1212 | |
1213 auto sh = b.signalHandler; | |
1214 | |
1215 b.scorched.connect(&foo); | |
1216 assert(sh.connections.length == 1); | |
1217 assert(b.signalId1 == 0); | |
1218 auto scCons = &sh.connections[0]; | |
1219 | |
1220 assert(scCons.getSlotList!(SlotListId.Func).length == 1); | |
1221 b.scorched.emit(1); | |
1222 assert(fooSum == 1); | |
1223 | |
1224 b.scorched.connect(&bar, ConnectionFlags.NoObject); | |
1225 assert(sh.connections.length == 1); | |
1226 assert(scCons.getSlotList!(SlotListId.Strong).length == 1); | |
1227 b.scorched.emit(1); | |
1228 assert (fooSum == 2 && barSum == 1); | |
1229 | |
1230 b.scorched.connect(&b.baz); | |
1231 assert(scCons.getSlotList!(SlotListId.Weak).length == 1); | |
1232 b.scorched.emit(1); | |
1233 assert (fooSum == 3 && barSum == 2 && b.bazSum == 1); | |
1234 | |
1235 b.scorched.disconnect(&bar); | |
1236 assert(scCons.slotCount == 2); | |
1237 b.scorched.disconnect(&b.baz); | |
1238 assert(scCons.slotCount == 1); | |
1239 b.scorched.disconnect(&foo); | |
1240 assert(scCons.slotCount == 0); | |
1241 assert(b.signalId2 == 0); | |
1242 | |
1243 fooSum = 0; | |
1244 void connectFoo() | |
1245 { | |
1246 b.scorched.connect(&foo); | |
1247 b.scorched.disconnect(&connectFoo); | |
1248 } | |
1249 | |
1250 b.scorched.connect(&connectFoo, ConnectionFlags.NoObject); | |
1251 b.scorched.emit(1); | |
1252 assert(scCons.getSlotList!(SlotListId.Func).length == 1); | |
1253 assert(scCons.getSlotList!(SlotListId.Strong).length == 0); | |
1254 assert(!fooSum); | |
1255 | |
1256 auto r = new B(); | |
1257 b.scorched.connect(&r.baz); | |
1258 assert(scCons.getSlotList!(SlotListId.Weak).length == 1); | |
1259 b.scorched.emit(1); | |
1260 assert(r.bazSum == 1); | |
1261 assert(fooSum == 1); | |
1262 | |
1263 delete(r); | |
1264 assert(scCons.getSlotList!(SlotListId.Weak).length == 1); | |
1265 b.scorched.emit(1); | |
1266 assert(scCons.getSlotList!(SlotListId.Weak).length == 0); | |
1267 } |