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