Mercurial > projects > qtd
annotate d2/qtd/QtdObject.d @ 315:2049c3abd348 lifetime
more cleanup
author | maxter <spambox@d-coding.com> |
---|---|
date | Wed, 23 Dec 2009 23:54:39 +0200 |
parents | 80b52f5e97b6 |
children |
rev | line source |
---|---|
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 | |
314
80b52f5e97b6
Structure without common root dir
maxter <spambox@d-coding.com>
parents:
311
diff
changeset
|
12 module qtd.QtdObject; |
311 | 13 |
14 import | |
15 core.memory, | |
314
80b52f5e97b6
Structure without common root dir
maxter <spambox@d-coding.com>
parents:
311
diff
changeset
|
16 qtd.Signal, |
80b52f5e97b6
Structure without common root dir
maxter <spambox@d-coding.com>
parents:
311
diff
changeset
|
17 qtd.Core, |
80b52f5e97b6
Structure without common root dir
maxter <spambox@d-coding.com>
parents:
311
diff
changeset
|
18 qtd.Memory, |
80b52f5e97b6
Structure without common root dir
maxter <spambox@d-coding.com>
parents:
311
diff
changeset
|
19 qtd.Array; |
311 | 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 */ | |
315 | 293 /+ |
311 | 294 void __ownership(QtdOwnership native) |
295 { | |
296 switch(own) | |
297 { | |
298 case QtdOwnership.cpp: | |
299 if (!__isPinned) | |
300 __pin; | |
301 break; | |
302 case QtdOwnership.cpp: | |
303 if(!__isPinned) | |
304 __pin; | |
305 break; | |
306 case QtdOwnership.def: | |
307 assert(false, "Not implemented"); | |
308 if (!(__flags & QtdObjectFlags.hasDId)) | |
309 __pin; | |
310 default: | |
311 assert(false); | |
312 } | |
313 } | |
315 | 314 +/ |
311 | 315 |
316 /** | |
317 Returns true if garbage collection for this object is disabled. | |
318 */ | |
319 final bool __isPinned() | |
320 { | |
321 return __prev || __root is this; | |
322 } | |
323 | |
324 // COMPILER BUG: 3206 | |
325 protected void __deleteNative() | |
326 { | |
327 assert(false); | |
328 } | |
329 | |
330 ~this() | |
331 { | |
332 if (!(__flags & QtdObjectFlags.skipNativeDelete)) | |
333 __dispose; | |
334 } | |
335 } | |
336 | |
337 /** | |
338 Base class for non-QObjects. | |
339 */ | |
340 abstract class QtdObject : QtdObjectBase | |
341 { | |
342 alias typeof(this) This; | |
343 | |
344 // TODO: must be abstract | |
345 QtdMetaObject metaObject() | |
346 { | |
347 return null; | |
348 } | |
349 | |
350 /** | |
351 Constructs the object. | |
352 */ | |
353 this(void* nativeId, QtdObjectFlags flags = QtdObjectFlags.none) | |
354 { | |
355 super(nativeId, flags); | |
315 | 356 if (!(__flags & QtdObjectFlags.hasDId)) |
311 | 357 metaObject.addRef(this); |
358 } | |
359 | |
360 ~this() | |
361 { | |
315 | 362 if (!(__flags & QtdObjectFlags.hasDId)) |
311 | 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 | |
315 | 382 /+ |
311 | 383 extern(C) void qtd_ownership(void* dId, QtdOwnership own) |
384 { | |
385 auto obj = cast(QtdObjectBase)dId; | |
386 obj.__ownership = own; | |
315 | 387 } |
388 +/ |