Mercurial > projects > qtd
comparison qt/d1/qt/QtdObject.d @ 261:8f7bb7fc3123 lifetime
Preparing for a better world
author | maxter |
---|---|
date | Mon, 21 Sep 2009 13:11:04 +0000 |
parents | b5773ccab07d |
children | 90131f64c9c9 |
comparison
equal
deleted
inserted
replaced
260:b5773ccab07d | 261:8f7bb7fc3123 |
---|---|
20 | 20 |
21 enum QtdObjectFlags : ubyte | 21 enum QtdObjectFlags : ubyte |
22 { | 22 { |
23 none, | 23 none, |
24 // The native object will not be deleted when the wrapper is deleted | 24 // The native object will not be deleted when the wrapper is deleted |
25 skipNativeDelete = 0b0001, | 25 skipNativeDelete = 0b0_0001, |
26 skipDDelete = 0b0010, | 26 // The wrapper will not be deleted when the native object is deleted |
27 hasDId = 0b0100, | 27 skipDDelete = 0b0_0010, |
28 stackAllocated = 0b1000 | 28 // D object reference is stored in the shell |
29 /+ | 29 hasDId = 0b0_0100, |
30 // The will be deleted when is goes out of scope. Implies skipNativeDelete | 30 // The wrapper is allocated on thread-local stack and destroyed at the end of the scope |
31 scoped = 0x08 | 31 stackAllocated = 0b0_1000 |
32 +/ | 32 // It is a QObject |
33 isQObject = 0b1_0000 | |
33 } | 34 } |
34 | 35 |
35 class MetaObject | 36 class MetaObject |
36 { | 37 { |
37 alias typeof(this) This; | 38 alias typeof(this) This; |
38 | 39 |
39 private | 40 private |
40 { | 41 { |
41 MetaObject _base; | 42 MetaObject _base; |
42 ClassInfo _classInfo; | 43 ClassInfo _classInfo; |
43 } | 44 } |
44 | 45 |
45 //COMPILER BUG: not accessible from QMetaObject | 46 //COMPILER BUG: not accessible from QMetaObject |
46 protected | 47 protected |
47 { | 48 { |
106 this(QtdMetaObjectBase base) | 107 this(QtdMetaObjectBase base) |
107 { | 108 { |
108 super(base); | 109 super(base); |
109 } | 110 } |
110 | 111 |
111 void construct(T : QtdObject, Concrete = T)() | 112 void construct(T : QtdObject)() |
112 { | 113 { |
113 super.construct!(T); | 114 super.construct!(T); |
114 _createWrapper = &T.__createWrapper; | 115 _createWrapper = &T.__createWrapper; |
115 } | 116 } |
116 } | 117 } |
117 | 118 |
118 /++ | 119 |
119 Meta-object for polymorphic Qt classes. | |
120 +/ | |
121 final class QtdMetaObject : QtdMetaObjectBase | 120 final class QtdMetaObject : QtdMetaObjectBase |
122 { | 121 { |
123 alias typeof(this) This; | 122 alias typeof(this) This; |
124 | 123 |
125 private void* _typeId; | 124 private void* _typeId; |
150 | 149 |
151 return static_cast!(QtdObject)(_createWrapper(nativeId, flags)); | 150 return static_cast!(QtdObject)(_createWrapper(nativeId, flags)); |
152 } | 151 } |
153 } | 152 } |
154 | 153 |
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 | |
155 abstract class QtdObjectBase | 180 abstract class QtdObjectBase |
156 { | 181 { |
157 alias typeof(this) This; | 182 alias typeof(this) This; |
158 | 183 |
159 void* __nativeId; | 184 void* __nativeId; |
160 QtdObjectFlags __flags; | 185 QtdObjectFlags __flags; |
161 | 186 |
162 new (size_t size, QtdObjectFlags flags = QtdObjectFlags.none) | 187 new (size_t size, QtdObjectFlags flags = QtdObjectFlags.none) |
163 { | 188 { |
164 return flags & QtdObjectFlags.stackAllocated ? __stackAlloc.alloc(size) : | 189 return flags & QtdObjectFlags.stackAllocated ? __stackAlloc.alloc(size) : |
165 GC.malloc(size, GC.BlkAttr.FINALIZE); | 190 GC.malloc(size, GC.BlkAttr.FINALIZE); |
166 } | 191 } |
175 | 200 |
176 this(void* nativeId, QtdObjectFlags flags = QtdObjectFlags.none) | 201 this(void* nativeId, QtdObjectFlags flags = QtdObjectFlags.none) |
177 { | 202 { |
178 __nativeId = nativeId; | 203 __nativeId = nativeId; |
179 __flags = flags; | 204 __flags = flags; |
205 | |
180 debug(QtdVerbose) __print("D wrapper constructed"); | 206 debug(QtdVerbose) __print("D wrapper constructed"); |
181 } | 207 } |
182 | 208 |
183 debug(QtdVerbose) | 209 debug(QtdVerbose) |
184 { | 210 { |
199 { | 225 { |
200 debug(QtdVerbose) __print("In QtdObjectBase destructor"); | 226 debug(QtdVerbose) __print("In QtdObjectBase destructor"); |
201 | 227 |
202 if (!(__flags & QtdObjectFlags.skipNativeDelete)) | 228 if (!(__flags & QtdObjectFlags.skipNativeDelete)) |
203 { | 229 { |
230 // Avoid deleting the wrapper twice | |
204 __flags |= QtdObjectFlags.skipDDelete; | 231 __flags |= QtdObjectFlags.skipDDelete; |
205 debug(QtdVerbose) __print("About to call native delete"); | 232 debug(QtdVerbose) __print("About to call native delete"); |
206 __deleteNative; | 233 __deleteNative; |
207 } | 234 } |
208 } | 235 } |
209 } | 236 } |
210 | 237 |
211 // Base class for by-reference objects | 238 // Base class for by-reference objects |
212 abstract class QtdObject : QtdObjectBase | 239 abstract class QtdObject : QtdObjectBase |
213 { | 240 { |
214 private | 241 private |
215 { | 242 { |
216 typeof(this) __next, __prev; | 243 typeof(this) __next, __prev; |
244 ubyte __nativeRef_; | |
217 static typeof(this) __root; | 245 static typeof(this) __root; |
218 } | |
219 | |
220 /++ | |
221 Use this method instead of 'is' operator to check if two D objects | |
222 wrap the same native object. | |
223 +/ | |
224 bool isSame(QtdObject other) | |
225 { | |
226 return __nativeId == other.__nativeId; | |
227 } | 246 } |
228 | 247 |
229 mixin SignalHandlerOps; | 248 mixin SignalHandlerOps; |
230 | 249 |
231 this(void* nativeId, QtdObjectFlags flags) | 250 this(void* nativeId, QtdObjectFlags flags) |
232 { | 251 { |
233 super (nativeId, flags); | 252 super (nativeId, flags); |
234 if (!(flags & QtdObjectFlags.skipNativeDelete)) | 253 |
235 __pin; | 254 if (!(flags & QtdObjectFlags.isQObject) && !(flags & QtdObjectFlags.hasDId)) |
236 } | 255 __addIdMapping; |
237 | 256 } |
238 final void __pin() | 257 |
239 { | 258 void __addIdMapping() {} |
240 debug(QtdVerbose) __print("Pinning"); | 259 void __removeIdMapping() {} |
241 | 260 |
242 __next = __root; | 261 final void __nativeRef() |
243 __root = this; | 262 { |
244 if (__next) | 263 assert (__nativeRef_ < 255); |
245 __next.__prev = this; | 264 |
246 } | 265 if (!__nativeRef_) |
247 | 266 { |
248 final void __unpin() | 267 __next = __root; |
249 { | 268 __root = this; |
250 debug(QtdVerbose) __print("Unpinning"); | 269 if (__next) |
251 | 270 __next.__prev = this; |
252 if (__prev) | 271 } |
253 __prev.__next = __next; | 272 __nativeRef_++; |
254 else | 273 |
255 __root = __next; | 274 debug(QtdVerbose) __print("Native ref incremented"); |
256 | 275 } |
257 if (__next) | 276 |
258 __next.__prev = __prev; | 277 final void __nativeDeref() |
259 } | 278 { |
260 | 279 assert (__nativeRef > 0); |
261 void __nativeOwnership(bool value) | 280 __nativeRef_--; |
262 { | 281 |
263 if (value) | 282 if (!__nativeRef_) |
264 { | 283 { |
265 assert (!(__flags & QtdObjectFlags.skipNativeDelete)); | 284 if (__prev) |
266 __flags |= QtdObjectFlags.skipNativeDelete; | 285 __prev.__next = __next; |
267 __unpin; | 286 else |
268 } | 287 __root = __next; |
269 else | 288 |
270 { | 289 if (__next) |
271 assert (__flags & QtdObjectFlags.skipNativeDelete); | 290 __next.__prev = __prev; |
272 __flags = __flags &= ~QtdObjectFlags.skipNativeDelete; | 291 } |
273 __pin; | 292 |
274 } | 293 debug(QtdVerbose) __print("Native ref decremented"); |
275 } | 294 } |
276 | 295 |
277 ~this() | 296 ~this() |
278 { | 297 { |
279 debug(QtdVerbose) __print("In QtdObject destructor"); | 298 if (!(__flags & QtdObjectFlags.isQObject) && !(__flags & QtdObjectFlags.hasDId)) |
280 | 299 __removeMapping; |
281 if (__prev || __root is this) | 300 |
282 __unpin; | 301 if (__nativeRef_) |
283 } | 302 { |
284 } | 303 if (__nativeRef_ > 1) |
285 | 304 { |
286 /++ | 305 debug(QtdVerbose) __print("Native ref is greater then 1 when deleting the object"); |
287 +/ | 306 __nativeRef_ = 1; |
288 void dispose(QtdObjectBase obj) | 307 } |
289 { | 308 __nativeDeref; |
290 obj.__flags &= ~QtdObjectFlags.skipNativeDelete; | 309 } |
291 delete obj; | 310 } |
292 } | 311 } |
293 | 312 |
294 // Called from shell destructors | 313 // Called from shell destructors |
295 extern(C) void qtd_delete_d_object(void* dId) | 314 extern(C) void qtd_delete_d_object(void* dId) |
296 { | 315 { |
302 // Avoid deleting native object twice | 321 // Avoid deleting native object twice |
303 obj.__flags |= QtdObjectFlags.skipNativeDelete; | 322 obj.__flags |= QtdObjectFlags.skipNativeDelete; |
304 delete obj; | 323 delete obj; |
305 } | 324 } |
306 } | 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 |