311
|
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>
|
|
5 *
|
|
6 * Copyright QtD Team, 2008-2009
|
|
7 * Distributed under the Boost Software License, Version 1.0.
|
|
8 * (See accompanying file boost-license-1.0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
9 *
|
|
10 */
|
|
11
|
|
12 module qt.QtdObject;
|
|
13
|
|
14 import
|
|
15 core.memory,
|
|
16 qt.Signal,
|
|
17 qt.Core,
|
|
18 qt.Memory,
|
|
19 qt.Array;
|
|
20
|
|
21 struct ScopeObject(T : QtdObjectBase)
|
|
22 {
|
|
23 T obj;
|
|
24 alias obj this;
|
|
25
|
|
26 ~this()
|
|
27 {
|
|
28 if (obj.__flags & QtdObjectFlags.stackAllocated)
|
|
29 {
|
|
30 delete obj;
|
|
31 }
|
|
32 }
|
|
33 }
|
|
34
|
|
35 ScopeObject!T scopeObject(T : QtdObjectBase)(void* nativeId, QtdObjectFlags flags = QtdObjectFlags.none)
|
|
36 {
|
|
37 ScopeObject!T sObj;
|
|
38 sObj.obj = T.__wrap(nativeId, cast(QtdObjectFlags)(flags | QtdObjectFlags.skipNativeDelete
|
|
39 | QtdObjectFlags.stackAllocated));
|
|
40 return sObj;
|
|
41 }
|
|
42
|
|
43 class MetaObject
|
|
44 {
|
|
45 alias typeof(this) This;
|
|
46 mixin SignalHandlerOps;
|
|
47
|
|
48 private
|
|
49 {
|
|
50 MetaObject _base;
|
|
51 ClassInfo _classInfo;
|
|
52 }
|
|
53
|
|
54 //COMPILER BUG: not accessible from QMetaObject
|
|
55 protected
|
|
56 {
|
|
57 This _firstDerived;
|
|
58 This _next;
|
|
59 }
|
|
60
|
|
61 private void addDerived(This mo)
|
|
62 {
|
|
63 mo._next = _firstDerived;
|
|
64 _firstDerived = mo;
|
|
65 }
|
|
66
|
|
67 /**
|
|
68 Next sibling on this derivation level
|
|
69 */
|
|
70 final This next()
|
|
71 {
|
|
72 return _next;
|
|
73 }
|
|
74
|
|
75 /**
|
|
76 Head of the linked list of derived classes
|
|
77 */
|
|
78 final This firstDerived()
|
|
79 {
|
|
80 return _firstDerived;
|
|
81 }
|
|
82
|
|
83 // NOTE: construction is split between this non-templated constructor and 'construct' function below.
|
|
84 this(This base)
|
|
85 {
|
|
86 if (base)
|
|
87 {
|
|
88 base.addDerived(this);
|
|
89 _base = base;
|
|
90 }
|
|
91 }
|
|
92
|
|
93 // TODO: can be removed when D acquires templated constructors
|
|
94 void construct(T : Object)()
|
|
95 {
|
|
96 _classInfo = T.classinfo;
|
|
97 }
|
|
98
|
|
99 final This base()
|
|
100 {
|
|
101 return _base;
|
|
102 }
|
|
103
|
|
104 final ClassInfo classInfo()
|
|
105 {
|
|
106 return _classInfo;
|
|
107 }
|
|
108 }
|
|
109
|
|
110 /**
|
|
111 */
|
|
112 abstract class QtdMetaObjectBase : MetaObject
|
|
113 {
|
|
114 alias QtdObjectBase function(void* nativeId, QtdObjectFlags flags) CreateWrapper;
|
|
115 private void* _nativeId;
|
|
116 protected CreateWrapper _createWrapper;
|
|
117
|
|
118 this(void* nativeId, QtdMetaObjectBase base, CreateWrapper createWrapper)
|
|
119 {
|
|
120 super(base);
|
|
121 _nativeId = nativeId;
|
|
122 _createWrapper = createWrapper;
|
|
123 }
|
|
124
|
|
125 final void* nativeId()
|
|
126 {
|
|
127 return _nativeId;
|
|
128 }
|
|
129 }
|
|
130
|
|
131 /**
|
|
132 */
|
|
133 final class QtdMetaObject : QtdMetaObjectBase
|
|
134 {
|
|
135 alias typeof(this) This;
|
|
136
|
|
137 private
|
|
138 {
|
|
139 // TODO: optimize to use a sorted list or something
|
|
140 // to speed up accesses.
|
|
141 QtdObject[] _refs;
|
|
142 }
|
|
143
|
|
144 this(void* nativeId, QtdMetaObjectBase base, CreateWrapper createWrapper)
|
|
145 {
|
|
146 super(nativeId, base, createWrapper);
|
|
147 }
|
|
148
|
|
149 void addRef(QtdObject object)
|
|
150 {
|
|
151 append!CAlloc(_refs, object);
|
|
152 }
|
|
153
|
|
154 void removeRef(QtdObject object)
|
|
155 {
|
|
156 remove!CAlloc(_refs, object);
|
|
157 }
|
|
158
|
|
159 QtdObject wrap(void* nativeObjId, void* typeId, QtdObjectFlags flags = QtdObjectFlags.none)
|
|
160 {
|
|
161 if (typeId == nativeId)
|
|
162 {
|
|
163 // TODO: optimize
|
|
164 foreach (r; _refs)
|
|
165 {
|
|
166 if (r.__nativeId == nativeObjId)
|
|
167 return r;
|
|
168 }
|
|
169 }
|
|
170 else
|
|
171 {
|
|
172 for (auto mo = static_cast!(This)(_firstDerived); mo; mo = static_cast!(This)(mo._next))
|
|
173 {
|
|
174 if (auto obj = mo.wrap(nativeObjId, typeId, flags))
|
|
175 return obj;
|
|
176 }
|
|
177 }
|
|
178
|
|
179 return static_cast!(QtdObject)(_createWrapper(nativeObjId, flags));
|
|
180 }
|
|
181 }
|
|
182
|
|
183 /**
|
|
184 Inserted into any QtD object.
|
|
185 */
|
|
186
|
|
187 /**
|
|
188 */
|
|
189 enum QtdObjectFlags : ubyte
|
|
190 {
|
|
191 none,
|
|
192 // The native object will not be deleted when the wrapper is deleted
|
|
193 skipNativeDelete = 0b0000_0001,
|
|
194 // The wrapper will not be deleted when the native object is deleted
|
|
195 skipDDelete = 0b0000_0010,
|
|
196 // The wrapper reference is stored in the shell
|
|
197 hasDId = 0b0000_0100,
|
|
198 // The wrapper is allocated on thread-local stack
|
|
199 stackAllocated = 0b0000_1000,
|
|
200 // is a QObject
|
|
201 isQObject = 0b0001_0000,
|
|
202 // The wrapper is not subject to GC
|
|
203 pinned = 0b0010_0000
|
|
204 }
|
|
205
|
|
206 class QtdObjectBase
|
|
207 {
|
|
208 // TODO: probably, __ should be replaced with qtd_, as __ are reserved by the language
|
|
209 /// Internal members. Do not change.
|
|
210 void* __nativeId;
|
|
211 /// ditto
|
|
212 QtdObjectFlags __flags;
|
|
213
|
|
214 private
|
|
215 {
|
|
216 QtdObjectBase __prev, __next;
|
|
217 static QtdObjectBase __root;
|
|
218 }
|
|
219
|
|
220 new (size_t size, QtdObjectFlags flags = QtdObjectFlags.none)
|
|
221 {
|
|
222 return flags & QtdObjectFlags.stackAllocated ? stackAlloc.alloc(size) :
|
|
223 GC.malloc(size, GC.BlkAttr.FINALIZE);
|
|
224 }
|
|
225
|
|
226 delete (void* p)
|
|
227 {
|
|
228 if ((cast(typeof(this))p).__flags & QtdObjectFlags.stackAllocated)
|
|
229 stackAlloc.free(this.classinfo.init.length);
|
|
230 else
|
|
231 GC.free(p);
|
|
232 }
|
|
233
|
|
234 /**
|
|
235 Tests if the other wrapper points to the same native object.
|
|
236 Should be always used when two objects that may have
|
|
237 duplicate wrappers are compared for identity.
|
|
238 */
|
|
239 bool __is(QtdObjectBase other)
|
|
240 {
|
|
241 return __nativeId == other.__nativeId;
|
|
242 }
|
|
243
|
|
244 /**
|
|
245 Constructs the object.
|
|
246 */
|
|
247 this(void* nativeId, QtdObjectFlags flags = QtdObjectFlags.none)
|
|
248 {
|
|
249 __nativeId = nativeId;
|
|
250 __flags = flags;
|
|
251 }
|
|
252
|
|
253 /**
|
|
254 Forces destruction of the native object.
|
|
255 */
|
|
256 final void __dispose()
|
|
257 {
|
|
258 // Avoid deleting the wrapper twice
|
|
259 __flags |= QtdObjectFlags.skipDDelete;
|
|
260 __deleteNative;
|
|
261 }
|
|
262
|
|
263 /**
|
|
264 Disables garbage collection for this object.
|
|
265 */
|
|
266 final void __pin()
|
|
267 {
|
|
268 assert (!__isPinned);
|
|
269 __next = __root;
|
|
270 __root = this;
|
|
271 if (__next)
|
|
272 __next.__prev = this;
|
|
273 }
|
|
274
|
|
275 /**
|
|
276 Enables garbage collection for this object.
|
|
277 */
|
|
278 final void __unpin()
|
|
279 {
|
|
280 assert (__isPinned);
|
|
281 if (__prev)
|
|
282 {
|
|
283 __prev.__next = __next;
|
|
284 __prev = null;
|
|
285 }
|
|
286 else
|
|
287 __root = __next;
|
|
288 }
|
|
289
|
|
290 /**
|
|
291
|
|
292 */
|
|
293 void __ownership(QtdOwnership native)
|
|
294 {
|
|
295 switch(own)
|
|
296 {
|
|
297 case QtdOwnership.cpp:
|
|
298 if (!__isPinned)
|
|
299 __pin;
|
|
300 break;
|
|
301 case QtdOwnership.cpp:
|
|
302 if(!__isPinned)
|
|
303 __pin;
|
|
304 break;
|
|
305 case QtdOwnership.def:
|
|
306 assert(false, "Not implemented");
|
|
307 if (!(__flags & QtdObjectFlags.hasDId))
|
|
308 __pin;
|
|
309 default:
|
|
310 assert(false);
|
|
311 }
|
|
312 }
|
|
313
|
|
314 /**
|
|
315 Returns true if garbage collection for this object is disabled.
|
|
316 */
|
|
317 final bool __isPinned()
|
|
318 {
|
|
319 return __prev || __root is this;
|
|
320 }
|
|
321
|
|
322 // COMPILER BUG: 3206
|
|
323 protected void __deleteNative()
|
|
324 {
|
|
325 assert(false);
|
|
326 }
|
|
327
|
|
328 ~this()
|
|
329 {
|
|
330 if (!(__flags & QtdObjectFlags.skipNativeDelete))
|
|
331 __dispose;
|
|
332 }
|
|
333 }
|
|
334
|
|
335 /**
|
|
336 Base class for non-QObjects.
|
|
337 */
|
|
338 abstract class QtdObject : QtdObjectBase
|
|
339 {
|
|
340 alias typeof(this) This;
|
|
341
|
|
342 // TODO: must be abstract
|
|
343 QtdMetaObject metaObject()
|
|
344 {
|
|
345 return null;
|
|
346 }
|
|
347
|
|
348 /**
|
|
349 Constructs the object.
|
|
350 */
|
|
351 this(void* nativeId, QtdObjectFlags flags = QtdObjectFlags.none)
|
|
352 {
|
|
353 super(nativeId, flags);
|
|
354 if (!(__flags & QtdObjectFlags.canHaveDups)
|
|
355 && !(__flags & QtdObjectFlags.hasDId))
|
|
356 metaObject.addRef(this);
|
|
357 }
|
|
358
|
|
359 ~this()
|
|
360 {
|
|
361 if (!(__flags & QtdObjectFlags.canHaveDups)
|
|
362 && !(__flags & QtdObjectFlags.hasDId))
|
|
363 metaObject.removeRef(this);
|
|
364 }
|
|
365
|
|
366 mixin SignalHandlerOps;
|
|
367 }
|
|
368
|
|
369 // Called from shell destructors
|
|
370 extern(C) void qtd_delete_d_object(void* dId)
|
|
371 {
|
|
372 auto obj = cast(QtdObjectBase)dId;
|
|
373
|
|
374 if (!(obj.__flags & QtdObjectFlags.skipDDelete))
|
|
375 {
|
|
376 // Avoid deleting native object twice
|
|
377 obj.__flags |= QtdObjectFlags.skipNativeDelete;
|
|
378 delete obj;
|
|
379 }
|
|
380 }
|
|
381
|
|
382 extern(C) void qtd_ownership(void* dId, QtdOwnership own)
|
|
383 {
|
|
384 auto obj = cast(QtdObjectBase)dId;
|
|
385 obj.__ownership = own;
|
|
386 } |