253
|
1 /**
|
|
2 *
|
|
3 * Copyright: Copyright QtD Team, 2008-2009
|
|
4 * License: <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>
|
258
|
5 * Authors: Max Samukha, Eldar Insafutdinov
|
253
|
6 *
|
|
7 * Copyright QtD Team, 2008-2009
|
|
8 * Distributed under the Boost Software License, Version 1.0.
|
|
9 * (See accompanying file boost-license-1.0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
258
|
10 *
|
253
|
11 */
|
|
12
|
|
13 module qt.QtdObject;
|
|
14
|
|
15 import qt.Signal;
|
258
|
16 import tango.core.Memory;
|
|
17 debug (QtdVerbose)
|
|
18 import tango.io.Stdout;
|
|
19
|
253
|
20
|
|
21 enum QtdObjectFlags : ubyte
|
|
22 {
|
|
23 none,
|
258
|
24 // The native object will not be deleted when the wrapper is deleted
|
261
|
25 skipNativeDelete = 0b0_0001,
|
|
26 // The wrapper will not be deleted when the native object is deleted
|
|
27 skipDDelete = 0b0_0010,
|
|
28 // D object reference is stored in the shell
|
|
29 hasDId = 0b0_0100,
|
|
30 // The wrapper is allocated on thread-local stack and destroyed at the end of the scope
|
|
31 stackAllocated = 0b0_1000
|
|
32 // It is a QObject
|
|
33 isQObject = 0b1_0000
|
253
|
34 }
|
|
35
|
258
|
36 class MetaObject
|
253
|
37 {
|
258
|
38 alias typeof(this) This;
|
|
39
|
|
40 private
|
|
41 {
|
|
42 MetaObject _base;
|
261
|
43 ClassInfo _classInfo;
|
258
|
44 }
|
|
45
|
|
46 //COMPILER BUG: not accessible from QMetaObject
|
|
47 protected
|
|
48 {
|
|
49 This _firstDerived;
|
|
50 This _next;
|
|
51 }
|
|
52
|
|
53 private void addDerived(This mo)
|
|
54 {
|
|
55 mo._next = _firstDerived;
|
|
56 _firstDerived = mo;
|
|
57 }
|
|
58
|
|
59 /++
|
|
60 Next sibling on this derivation level
|
|
61 +/
|
|
62 final This next()
|
|
63 {
|
|
64 return _next;
|
|
65 }
|
|
66
|
|
67 /++
|
|
68 Head of the linked list of derived classes
|
|
69 +/
|
|
70 final This firstDerived()
|
|
71 {
|
|
72 return _firstDerived;
|
|
73 }
|
|
74
|
|
75 // NOTE: construction is split between this non-templated constructor and 'construct' function below.
|
|
76 this(This base)
|
|
77 {
|
|
78 if (base)
|
|
79 {
|
|
80 base.addDerived(this);
|
|
81 _base = base;
|
|
82 }
|
|
83 }
|
|
84
|
|
85 // TODO: can be removed when D acquires templated constructors
|
|
86 void construct(T : Object)()
|
|
87 {
|
|
88 _classInfo = T.classinfo;
|
|
89 }
|
|
90
|
|
91 final This base()
|
|
92 {
|
|
93 return _base;
|
|
94 }
|
|
95
|
|
96 final ClassInfo classInfo()
|
|
97 {
|
|
98 return _classInfo;
|
|
99 }
|
|
100 }
|
|
101
|
|
102
|
260
|
103 abstract class QtdMetaObjectBase : MetaObject
|
258
|
104 {
|
|
105 QtdObjectBase function(void* nativeId, QtdObjectFlags flags) _createWrapper;
|
|
106
|
260
|
107 this(QtdMetaObjectBase base)
|
|
108 {
|
|
109 super(base);
|
|
110 }
|
|
111
|
261
|
112 void construct(T : QtdObject)()
|
258
|
113 {
|
|
114 super.construct!(T);
|
|
115 _createWrapper = &T.__createWrapper;
|
|
116 }
|
|
117 }
|
|
118
|
261
|
119
|
260
|
120 final class QtdMetaObject : QtdMetaObjectBase
|
258
|
121 {
|
|
122 alias typeof(this) This;
|
|
123
|
|
124 private void* _typeId;
|
|
125
|
|
126 this(void* typeId, QtdMetaObject base)
|
|
127 {
|
|
128 super(base);
|
|
129 _typeId = typeId;
|
|
130 }
|
|
131
|
|
132 QtdObject wrap(void* nativeId, void* typeId, QtdObjectFlags flags = QtdObjectFlags.skipNativeDelete)
|
|
133 {
|
|
134 if (typeId == _typeId)
|
|
135 {
|
|
136 /+
|
|
137 if (auto p = nativeId in _nativeToDMap)
|
|
138 return *p;
|
|
139 +/
|
|
140 }
|
|
141 else
|
|
142 {
|
|
143 for (auto mo = static_cast!(This)(_firstDerived); mo; mo = static_cast!(This)(mo._next))
|
|
144 {
|
|
145 if (auto obj = mo.wrap(nativeId, typeId, flags))
|
|
146 return obj;
|
|
147 }
|
|
148 }
|
|
149
|
260
|
150 return static_cast!(QtdObject)(_createWrapper(nativeId, flags));
|
258
|
151 }
|
|
152 }
|
|
153
|
261
|
154 class IdMappings
|
|
155 {
|
|
156 private void* _data;
|
|
157
|
|
158 this()
|
|
159 {
|
|
160 }
|
|
161
|
|
162 void add(void* nativeId, void* dId)
|
|
163 {
|
|
164 }
|
|
165
|
|
166 void remove(void* dId)
|
|
167 {
|
|
168 }
|
|
169
|
|
170 void* opIndex[void* nativeId]
|
|
171 {
|
|
172 }
|
|
173
|
|
174 ~this()
|
|
175 {
|
|
176 free(_data);
|
|
177 }
|
|
178 }
|
|
179
|
258
|
180 abstract class QtdObjectBase
|
261
|
181 {
|
258
|
182 alias typeof(this) This;
|
|
183
|
253
|
184 void* __nativeId;
|
258
|
185 QtdObjectFlags __flags;
|
261
|
186
|
258
|
187 new (size_t size, QtdObjectFlags flags = QtdObjectFlags.none)
|
|
188 {
|
|
189 return flags & QtdObjectFlags.stackAllocated ? __stackAlloc.alloc(size) :
|
|
190 GC.malloc(size, GC.BlkAttr.FINALIZE);
|
|
191 }
|
|
192
|
|
193 delete (void* p)
|
|
194 {
|
|
195 if ((cast(This)p).__flags & QtdObjectFlags.stackAllocated)
|
|
196 __stackAlloc.free(this.classinfo.init.length);
|
|
197 else
|
|
198 GC.free(p);
|
|
199 }
|
|
200
|
253
|
201 this(void* nativeId, QtdObjectFlags flags = QtdObjectFlags.none)
|
|
202 {
|
|
203 __nativeId = nativeId;
|
258
|
204 __flags = flags;
|
261
|
205
|
258
|
206 debug(QtdVerbose) __print("D wrapper constructed");
|
253
|
207 }
|
258
|
208
|
|
209 debug(QtdVerbose)
|
|
210 {
|
|
211 void __print(string msg)
|
|
212 {
|
|
213 Stdout.formatln("{} (native: {}, D: {}, flags 0b{:b})", msg, __nativeId, cast(void*)this, __flags);
|
|
214 }
|
253
|
215 }
|
258
|
216
|
253
|
217 protected void __deleteNative()
|
|
218 {
|
258
|
219 assert(false, "Cannot delete native "
|
|
220 ~ this.classinfo.name
|
|
221 ~ " because it has no public destructor");
|
253
|
222 }
|
258
|
223
|
253
|
224 ~this()
|
|
225 {
|
258
|
226 debug(QtdVerbose) __print("In QtdObjectBase destructor");
|
|
227
|
|
228 if (!(__flags & QtdObjectFlags.skipNativeDelete))
|
253
|
229 {
|
261
|
230 // Avoid deleting the wrapper twice
|
258
|
231 __flags |= QtdObjectFlags.skipDDelete;
|
|
232 debug(QtdVerbose) __print("About to call native delete");
|
253
|
233 __deleteNative;
|
261
|
234 }
|
258
|
235 }
|
|
236 }
|
|
237
|
|
238 // Base class for by-reference objects
|
|
239 abstract class QtdObject : QtdObjectBase
|
|
240 {
|
|
241 private
|
|
242 {
|
|
243 typeof(this) __next, __prev;
|
261
|
244 ubyte __nativeRef_;
|
258
|
245 static typeof(this) __root;
|
|
246 }
|
|
247
|
|
248 mixin SignalHandlerOps;
|
|
249
|
|
250 this(void* nativeId, QtdObjectFlags flags)
|
|
251 {
|
261
|
252 super (nativeId, flags);
|
|
253
|
|
254 if (!(flags & QtdObjectFlags.isQObject) && !(flags & QtdObjectFlags.hasDId))
|
|
255 __addIdMapping;
|
258
|
256 }
|
|
257
|
261
|
258 void __addIdMapping() {}
|
|
259 void __removeIdMapping() {}
|
258
|
260
|
261
|
261 final void __nativeRef()
|
258
|
262 {
|
261
|
263 assert (__nativeRef_ < 255);
|
258
|
264
|
261
|
265 if (!__nativeRef_)
|
|
266 {
|
|
267 __next = __root;
|
|
268 __root = this;
|
|
269 if (__next)
|
|
270 __next.__prev = this;
|
|
271 }
|
|
272 __nativeRef_++;
|
|
273
|
|
274 debug(QtdVerbose) __print("Native ref incremented");
|
258
|
275 }
|
|
276
|
261
|
277 final void __nativeDeref()
|
|
278 {
|
|
279 assert (__nativeRef > 0);
|
|
280 __nativeRef_--;
|
|
281
|
|
282 if (!__nativeRef_)
|
258
|
283 {
|
261
|
284 if (__prev)
|
|
285 __prev.__next = __next;
|
|
286 else
|
|
287 __root = __next;
|
|
288
|
|
289 if (__next)
|
|
290 __next.__prev = __prev;
|
253
|
291 }
|
261
|
292
|
|
293 debug(QtdVerbose) __print("Native ref decremented");
|
|
294 }
|
|
295
|
|
296 ~this()
|
|
297 {
|
|
298 if (!(__flags & QtdObjectFlags.isQObject) && !(__flags & QtdObjectFlags.hasDId))
|
|
299 __removeMapping;
|
|
300
|
|
301 if (__nativeRef_)
|
258
|
302 {
|
261
|
303 if (__nativeRef_ > 1)
|
|
304 {
|
|
305 debug(QtdVerbose) __print("Native ref is greater then 1 when deleting the object");
|
|
306 __nativeRef_ = 1;
|
|
307 }
|
|
308 __nativeDeref;
|
258
|
309 }
|
|
310 }
|
|
311 }
|
|
312
|
|
313 // Called from shell destructors
|
|
314 extern(C) void qtd_delete_d_object(void* dId)
|
|
315 {
|
|
316 auto obj = cast(QtdObject)dId;
|
|
317 debug(QtdVerbose) obj.__print("In qtd_delete_d_object");
|
|
318
|
|
319 if (!(obj.__flags & QtdObjectFlags.skipDDelete))
|
|
320 {
|
|
321 // Avoid deleting native object twice
|
|
322 obj.__flags |= QtdObjectFlags.skipNativeDelete;
|
|
323 delete obj;
|
253
|
324 }
|
261
|
325 }
|
|
326
|
|
327 extern(C) void qtd_native_ref(void* dId)
|
|
328 {
|
|
329 (cast(QtdObject)dId).__nativeRef;
|
|
330 }
|
|
331
|
|
332 extern(C) void qtd_native_deref(void* dId)
|
|
333 {
|
|
334 (cast(QtdObject)dId).__nativeDeref;
|
|
335 }
|
|
336
|
|
337
|