annotate qt/d1/qt/Signal.d @ 16:6faf3d3cb95e

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