Mercurial > projects > qtd
annotate qt/d2/qt/Signal.d @ 282:256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
author | eldar |
---|---|
date | Fri, 16 Oct 2009 02:43:59 +0000 |
parents | 519befd5a5d1 |
children | 1f6923c8cba0 |
rev | line source |
---|---|
1 | 1 /** |
2 * | |
3 * Copyright: Copyright QtD Team, 2008-2009 | |
4 * Authors: Max Samukha, Eldar Insafutdinov | |
5 * License: <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a> | |
6 * | |
7 * Copyright QtD Team, 2008-2009 | |
8 * Distributed under the Boost Software License, Version 1.0. | |
9 * (See accompanying file boost-license-1.0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
10 * | |
11 */ | |
16 | 12 module qt.Signal; |
1 | 13 |
14 public import qt.QGlobal; | |
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 //TODO: this could be avoided if named mixins didn't suck. | |
785 public struct SignalOps(int sigId, A...) | |
786 { | |
787 private SignalHandler sh; | |
788 enum { signalId = sigId } | |
789 | |
790 void emit(A args) | |
791 { | |
792 sh.emit(signalId, args); | |
793 } | |
794 | |
795 debug size_t slotCount() | |
796 { | |
797 return sh.slotCount(signalId); | |
798 } | |
799 } | |
800 | |
801 public template SignalHandlerOps() | |
802 { | |
803 static assert (is(typeof(this.signalHandler)), | |
804 "SignalHandlerOps is already instantiated in " ~ typeof(this).stringof ~ " or one of its base classes"); | |
805 | |
806 protected: | |
807 SignalHandler signalHandler_; // manages signal-to-slot connections | |
808 | |
809 final SignalHandler signalHandler() | |
810 { | |
811 if (!signalHandler_) | |
812 { | |
813 signalHandler_ = new SignalHandler(this); | |
814 onSignalHandlerCreated(signalHandler_); | |
815 } | |
816 return signalHandler_; | |
817 } | |
818 | |
819 void onSignalHandlerCreated(ref SignalHandler sh) | |
820 { | |
821 } | |
822 | |
823 public: | |
824 final void blockSignals() | |
825 { | |
826 signalHandler.blockSignals(); | |
827 } | |
828 | |
829 final void unblockSignals() | |
830 { | |
831 signalHandler.unblockSignals(); | |
832 } | |
278 | 833 |
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
|
834 template connect(string signalName, A...) |
278 | 835 { |
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
|
836 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
|
837 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
|
838 { |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 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
|
840 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
|
841 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
|
842 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
|
843 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
|
844 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
|
845 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
|
846 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
|
847 } |
278 | 848 } |
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 template disconnect(string signalName, A...) |
278 | 851 { |
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
|
852 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
|
853 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
|
854 { |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 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
|
856 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
|
857 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
|
858 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
|
859 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
|
860 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
|
861 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
|
862 } |
278 | 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 /* |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 template slotCount(string signalName, A...) |
278 | 866 { |
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
|
867 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
|
868 { |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 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
|
870 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
|
871 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
|
872 } |
278 | 873 } |
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
|
874 */ |
1 | 875 } |
876 | |
877 /** | |
278 | 878 New implementation. |
879 */ | |
880 | |
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
|
881 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
|
882 |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 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
|
884 |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 template isDg(Dg) |
278 | 886 { |
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
|
887 enum isDg = is(Dg == delegate); |
278 | 888 } |
889 | |
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
|
890 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
|
891 { |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 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
|
893 } |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
279
diff
changeset
|
894 |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 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
|
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 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
|
898 } |
278 | 899 |
900 string joinArgs(A...)() | |
901 { | |
902 string res = ""; | |
903 static if(A.length) | |
904 { | |
905 res = A[0].stringof; | |
906 foreach(k; A[1..$]) | |
907 res ~= "," ~ k.stringof; | |
908 } | |
909 return res; | |
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 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
|
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 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
|
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 |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 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
|
918 { |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 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
|
920 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
|
921 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
|
922 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
|
923 } |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 template SignalPred(T1, T2) |
278 | 926 { |
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
|
927 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
|
928 } |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 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
|
931 { |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
279
diff
changeset
|
932 static 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
|
933 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
|
934 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
|
935 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
|
936 } |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
279
diff
changeset
|
937 |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 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
|
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 (i < Needle.at.length) |
278 | 941 { |
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
|
942 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
|
943 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
|
944 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
|
945 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
|
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 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
|
948 { |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 enum value = true; |
278 | 950 } |
951 } | |
952 | |
282
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
279
diff
changeset
|
953 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
|
954 { |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
279
diff
changeset
|
955 template 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
|
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 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
|
958 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
|
959 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
|
960 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
|
961 } |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 template SigBySignPred(string name, SigArgs...) |
278 | 965 { |
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
|
966 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
|
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 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
|
969 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
|
970 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
|
971 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
|
972 } |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 } |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 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
|
976 { |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 const string staticSymbolName = prefix ~ ToString!(id); |
278 | 978 } |
979 | |
980 template signatureString(string name, A...) | |
981 { | |
982 const string signatureString = name ~ "(" ~ joinArgs!(A) ~ ")"; | |
983 } | |
984 | |
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
|
985 template findSymbolImpl(string prefix, C, int id, alias pred) |
278 | 986 { |
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
|
987 static if ( is(typeof(mixin("C." ~ staticSymbolName!(prefix, id)))) ) |
278 | 988 { |
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
|
989 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
|
990 static if (pred!current) |
278 | 991 alias current result; |
992 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
|
993 alias findSymbolImpl!(prefix, C, id + 1, pred).result result; |
278 | 994 } |
995 else | |
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 alias void result; |
278 | 998 } |
999 } | |
1000 | |
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
|
1001 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
|
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 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
|
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 findSignal(C, string name, Receiver, SigArgs...) |
278 | 1007 { |
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
|
1008 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
|
1009 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
|
1010 { |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
279
diff
changeset
|
1011 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
|
1012 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
|
1013 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
|
1014 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
|
1015 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
|
1016 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
|
1017 } |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 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
|
1019 { |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both 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 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
|
1021 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
|
1022 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
|
1023 } |
278 | 1024 } |
1025 | |
1026 /** ---------------- */ | |
1027 | |
1028 | |
1029 /** | |
1 | 1030 Examples: |
1031 ---- | |
1032 struct Args | |
1033 { | |
1034 bool cancel; | |
1035 } | |
1036 | |
1037 class C | |
1038 { | |
1039 private int _x; | |
1040 // reference parameters are not supported yet, | |
1041 // so we pass arguments by pointer. | |
1042 mixin Signal!("xChanging", int, Args*); | |
1043 mixin Signal!("xChanged"); | |
1044 | |
1045 void x(int v) | |
1046 { | |
1047 if (v != _x) | |
1048 { | |
1049 Args args; | |
1050 xChanging.emit(v, &args); | |
1051 if (!args.cancel) | |
1052 { | |
1053 _x = v; | |
1054 xChanged.emit; | |
1055 } | |
1056 } | |
1057 } | |
1058 } | |
1059 ---- | |
1060 */ | |
1061 template Signal(string name, A...) | |
1062 { | |
1063 mixin SignalImpl!(0, name, A); | |
1064 } | |
1065 | |
1066 template SignalImpl(int index, string name, A...) | |
1067 { | |
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
|
1068 static if (is(typeof(mixin(typeof(this).stringof ~ ".__signal" ~ ToString!(index))))) |
1 | 1069 mixin SignalImpl!(index + 1, name, A); |
1070 else | |
1071 { | |
1072 // mixed-in once | |
1073 static if (!is(typeof(this.signalHandler))) | |
1074 { | |
1075 mixin SignalHandlerOps; | |
1076 } | |
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
|
1077 mixin("public alias TypeTuple!(\"" ~ name ~ "\", index, A) __signal" ~ ToString!(index) ~ ";"); |
1 | 1078 mixin("SignalOps!(" ~ ToString!(index) ~ ", A) " ~ name ~ "(){ return SignalOps!(" |
1079 ~ ToString!(index) ~ ", A)(signalHandler); }"); | |
1080 } | |
1081 } | |
1082 | |
1083 extern(C) alias void function(void*) SlotConnector; | |
1084 | |
1085 debug (UnitTest) | |
1086 { | |
1087 class A | |
1088 { | |
1089 mixin Signal!("scorched", int); | |
1090 | |
1091 int signalId1 = -1; | |
1092 int signalId2 = -1; | |
1093 | |
1094 void onFirstConnect(int sId) | |
1095 { | |
1096 signalId1 = sId; | |
1097 } | |
1098 | |
1099 void onLastDisconnect(int sId) | |
1100 { | |
1101 signalId2 = sId; | |
1102 } | |
1103 | |
1104 this() | |
1105 { | |
1106 signalHandler.firstSlotConnected = &onFirstConnect; | |
1107 signalHandler.lastSlotDisconnected = &onLastDisconnect; | |
1108 } | |
1109 } | |
1110 | |
1111 class B : A | |
1112 { | |
1113 mixin Signal!("booed", int); | |
1114 | |
1115 int bazSum; | |
1116 void baz(int i) | |
1117 { | |
1118 bazSum += i; | |
1119 } | |
1120 } | |
1121 | |
1122 class C : A | |
1123 { | |
1124 mixin Signal!("cooked"); | |
1125 } | |
1126 } | |
1127 | |
1128 unittest | |
1129 { | |
1130 static int fooSum; | |
1131 static int barSum; | |
1132 | |
1133 static void foo(int i) | |
1134 { | |
1135 fooSum += i; | |
1136 } | |
1137 | |
1138 void bar(long i) | |
1139 { | |
1140 barSum += i; | |
1141 } | |
1142 | |
1143 auto a = new A; | |
1144 auto b = new B; | |
1145 auto c = new C; | |
1146 assert(b.scorched.signalId == 0); | |
1147 assert(b.booed.signalId == 1); | |
1148 assert(c.cooked.signalId == 1); | |
1149 | |
1150 auto sh = b.signalHandler; | |
1151 | |
1152 b.scorched.connect(&foo); | |
1153 assert(sh.connections.length == 1); | |
1154 assert(b.signalId1 == 0); | |
1155 auto scCons = &sh.connections[0]; | |
1156 | |
1157 assert(scCons.getSlotList!(SlotListId.Func).length == 1); | |
1158 b.scorched.emit(1); | |
1159 assert(fooSum == 1); | |
1160 | |
1161 b.scorched.connect(&bar, ConnectionFlags.NoObject); | |
1162 assert(sh.connections.length == 1); | |
1163 assert(scCons.getSlotList!(SlotListId.Strong).length == 1); | |
1164 b.scorched.emit(1); | |
1165 assert (fooSum == 2 && barSum == 1); | |
1166 | |
1167 b.scorched.connect(&b.baz); | |
1168 assert(scCons.getSlotList!(SlotListId.Weak).length == 1); | |
1169 b.scorched.emit(1); | |
1170 assert (fooSum == 3 && barSum == 2 && b.bazSum == 1); | |
1171 | |
1172 b.scorched.disconnect(&bar); | |
1173 assert(scCons.slotCount == 2); | |
1174 b.scorched.disconnect(&b.baz); | |
1175 assert(scCons.slotCount == 1); | |
1176 b.scorched.disconnect(&foo); | |
1177 assert(scCons.slotCount == 0); | |
1178 assert(b.signalId2 == 0); | |
1179 | |
1180 fooSum = 0; | |
1181 void connectFoo() | |
1182 { | |
1183 b.scorched.connect(&foo); | |
1184 b.scorched.disconnect(&connectFoo); | |
1185 } | |
1186 | |
1187 b.scorched.connect(&connectFoo, ConnectionFlags.NoObject); | |
1188 b.scorched.emit(1); | |
1189 assert(scCons.getSlotList!(SlotListId.Func).length == 1); | |
1190 assert(scCons.getSlotList!(SlotListId.Strong).length == 0); | |
1191 assert(!fooSum); | |
1192 | |
1193 auto r = new B(); | |
1194 b.scorched.connect(&r.baz); | |
1195 assert(scCons.getSlotList!(SlotListId.Weak).length == 1); | |
1196 b.scorched.emit(1); | |
1197 assert(r.bazSum == 1); | |
1198 assert(fooSum == 1); | |
1199 | |
1200 delete(r); | |
1201 assert(scCons.getSlotList!(SlotListId.Weak).length == 1); | |
1202 b.scorched.emit(1); | |
1203 assert(scCons.getSlotList!(SlotListId.Weak).length == 0); | |
1204 } |