comparison d2/qtd/QtdObject.d @ 311:8674fd5f34f4 lifetime

Added d1/d2 top directories
author maxter <spambox@d-coding.com>
date Wed, 23 Dec 2009 16:17:22 +0200
parents
children 80b52f5e97b6
comparison
equal deleted inserted replaced
310:5bcfe9e7db7f 311:8674fd5f34f4
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 }