annotate qt/d1/qt/Signal.d @ 279:519befd5a5d1

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