annotate d2/qtd/QtdObject.d @ 382:1d56b2a2e10c

Fixes to debugging stuff. Added size_t as primitive type to workaround Qwt build failure in debug
author Max Samukha <maxter@spambox.com>
date Mon, 12 Jul 2010 20:36:07 +0300
parents a032df77b6ab
children bd7f485e3573
rev   line source
maxter@253 1 /**
maxter@253 2 *
maxter@372 3 * Copyright: Copyright QtD Team, 2008-2010
maxter@372 4 * License: Boost License 1.0
maxter@372 5 * Authors: Max Samukha, Eldar Insafutdinov
maxter@253 6 *
maxter@253 7 */
maxter@253 8
maxter@344 9 module qtd.QtdObject;
maxter@253 10
maxter@372 11 import
maxter@372 12 core.memory,
maxter@372 13 std.bitmanip,
maxter@372 14 qtd.Core,
maxter@372 15 qtd.Debug,
maxter@382 16 qtd.meta.Runtime;
maxter@372 17
maxter@372 18 /**
maxter@372 19 QtdObject initialization options.
maxter@372 20 */
maxter@372 21 enum QtdObjectInitFlags
maxter@253 22 {
maxter@253 23 none,
maxter@372 24 /// The wrapper is being created by user code.
maxter@372 25 createdByD = 0x1,
maxter@372 26 /// The wrapper is being created with native ownership.
maxter@372 27 nativeOwnership = 0x2,
maxter@372 28 /// The wrapper is allocated on stack.
maxter@372 29 onStack = 0x4
maxter@253 30 }
maxter@253 31
maxter@372 32 /**
maxter@372 33 */
maxter@372 34 enum QtdObjectOwnership
maxter@253 35 {
maxter@372 36 ///
maxter@372 37 native,
maxter@372 38 ///
maxter@372 39 d
maxter@372 40 }
maxter@253 41
maxter@372 42 /**
maxter@372 43 */
maxter@372 44 struct QtdObjectFlags
maxter@372 45 {
maxter@372 46 mixin (bitfields!(
maxter@372 47 bool, "nativeDeleteDisabled" , 1,
maxter@372 48 bool, "wrapperDeleteDisabled" , 1,
maxter@372 49 bool, "createdByD" , 1,
maxter@372 50 bool, "pinned" , 1,
maxter@372 51 bool, "isQObject" , 1,
maxter@372 52 bool, "polymorphic" , 1,
maxter@372 53 bool, "onStack" , 1,
maxter@372 54 int , "reserved" , 1
maxter@372 55 ));
maxter@372 56 }
maxter@372 57
maxter@372 58
maxter@372 59 /* package */ abstract class QtdObject
maxter@372 60 {
maxter@372 61 alias typeof(this) This;
maxter@372 62
maxter@372 63 private
maxter@253 64 {
maxter@372 65 void* _nativeId;
maxter@372 66 This _next;
maxter@372 67 This _prev;
maxter@372 68 __gshared static This _root;
maxter@253 69 }
maxter@253 70
maxter@372 71 protected QtdObjectFlags _flags;
maxter@372 72
maxter@372 73 /**
maxter@372 74 */
maxter@372 75 @property QtdObjectFlags qtdFlags()
maxter@253 76 {
maxter@372 77 return _flags;
maxter@253 78 }
maxter@253 79
maxter@372 80 /**
maxter@372 81 */
maxter@372 82 @property final const
maxter@253 83 {
maxter@372 84 void* qtdNativeId()
maxter@372 85 {
maxter@372 86 return cast(void*)_nativeId;
maxter@372 87 }
maxter@372 88
maxter@372 89 void qtdNativeId(void* v)
maxter@372 90 {
maxter@372 91 unqual(_nativeId) = v;
maxter@372 92 }
maxter@372 93 }
maxter@372 94
maxter@372 95 this(void* nativeId, QtdObjectInitFlags initFlags = QtdObjectInitFlags.none)
maxter@372 96 {
maxter@372 97 _nativeId = nativeId;
maxter@372 98
maxter@372 99 if (initFlags & QtdObjectInitFlags.createdByD)
maxter@372 100 _flags.createdByD = true;
maxter@372 101
maxter@372 102 if (initFlags & QtdObjectInitFlags.nativeOwnership)
maxter@372 103 qtdSetOwnership(QtdObjectOwnership.native);
maxter@372 104
maxter@372 105 if (initFlags & QtdObjectInitFlags.onStack)
maxter@372 106 {
maxter@372 107 //assert(!_flags.isQObject);
maxter@372 108 assert(!(initFlags & QtdObjectInitFlags.nativeOwnership));
maxter@372 109
maxter@372 110 _flags.nativeDeleteDisabled = true;
maxter@372 111 _flags.wrapperDeleteDisabled = true;
maxter@372 112 }
maxter@372 113
maxter@372 114 mixin(debugHandler("onWrapperConstructed", "this"));
maxter@372 115 }
maxter@372 116
maxter@372 117 /**
maxter@372 118 Disables GC for this object;
maxter@372 119 */
maxter@372 120 // TODO: needs to be properly synchronized
maxter@372 121 final void qtdPin() const
maxter@372 122 {
maxter@372 123 assert(!_flags.pinned);
maxter@372 124 //GC.addRoot(cast(void*)this);
maxter@372 125
maxter@372 126 auto obj = unqual(this);
maxter@372 127
maxter@372 128 obj._next = _root;
maxter@372 129 _root = obj;
maxter@372 130 if (_next)
maxter@372 131 obj._next._prev = obj;
maxter@372 132
maxter@372 133 obj._flags.pinned = true;
maxter@372 134 }
maxter@372 135
maxter@372 136 /**
maxter@372 137 Multiple wrappers for a single native object may exist.
maxter@372 138 This function is used to test that this and the other wrapper point
maxter@372 139 to the same native object (identity test).
maxter@372 140
maxter@372 141 Note that wrappers for QObject instances and instances of classes
maxter@372 142 derived from QObject are always unique, therefore
maxter@382 143 the 'is' operator can be used instead of this function.
maxter@372 144 */
maxter@372 145 final bool isSame(const(QtdObject) other) const
maxter@372 146 {
maxter@372 147 return other !is null && (other is this || other.qtdNativeId == qtdNativeId);
maxter@372 148 }
maxter@372 149
maxter@372 150 /**
maxter@372 151 Enables GC for this object.
maxter@372 152 */
maxter@372 153 // TODO: needs to be properly synchronized
maxter@372 154 final void qtdUnpin() const
maxter@372 155 {
maxter@372 156 assert(_flags.pinned);
maxter@372 157 //GC.removeRoot(cast(void*)this);
maxter@372 158
maxter@372 159 auto obj = unqual(this);
maxter@372 160 if (_prev)
maxter@372 161 obj._prev._next = obj._next;
maxter@253 162 else
maxter@372 163 _root = obj._next;
maxter@372 164
maxter@372 165 if (_next)
maxter@372 166 obj._next._prev = obj._prev;
maxter@372 167
maxter@372 168 obj._flags.pinned = false;
maxter@372 169 }
maxter@372 170
maxter@372 171 /**
maxter@372 172 Sets the ownership of this object.
maxter@372 173 Setting the same ownership twice results in undefined behavior.
maxter@372 174 The function is not thread-safe.
maxter@372 175 */
maxter@372 176 void qtdSetOwnership(QtdObjectOwnership own) const
maxter@372 177 {
maxter@372 178 if (_flags.isQObject)
maxter@372 179 return;
maxter@372 180
maxter@372 181 assert(!_flags.onStack);
maxter@372 182 auto obj = unqual(this);
maxter@372 183
maxter@372 184 if (own == QtdObjectOwnership.native)
maxter@372 185 {
maxter@372 186 if (_flags.polymorphic && _flags.createdByD)
maxter@372 187 qtdPin();
maxter@372 188 else
maxter@372 189 obj._flags.nativeDeleteDisabled = true;
maxter@372 190 }
maxter@372 191 else if (own == QtdObjectOwnership.d)
maxter@372 192 {
maxter@372 193 if (_flags.polymorphic && _flags.createdByD)
maxter@372 194 qtdUnpin();
maxter@372 195 else
maxter@372 196 obj._flags.nativeDeleteDisabled = false;
maxter@372 197 }
maxter@372 198 else
maxter@372 199 assert(false);
maxter@372 200
maxter@382 201 mixin(debugHandler("onObjectOwnershipChanged", "obj"));
maxter@253 202 }
maxter@253 203
maxter@253 204 // COMPILER BUG: 3206
maxter@372 205 protected void qtdDeleteNative()
maxter@253 206 {
maxter@253 207 assert(false);
maxter@253 208 }
maxter@253 209
maxter@253 210 ~this()
maxter@253 211 {
maxter@372 212 mixin(debugHandler("onWrapperDestruction", "this"));
maxter@372 213
maxter@372 214 if (!_flags.nativeDeleteDisabled)
maxter@253 215 {
maxter@253 216 // avoid deleting D object twice.
maxter@372 217
maxter@372 218 _flags.wrapperDeleteDisabled = true;
maxter@372 219 qtdDeleteNative;
maxter@372 220
maxter@372 221 mixin(debugHandler("onNativeDeleted", "this"));
maxter@253 222 }
maxter@372 223
maxter@372 224 if (_flags.pinned)
maxter@372 225 qtdUnpin();
maxter@372 226
maxter@372 227 mixin(debugHandler("onWrapperDestroyed", "this"));
maxter@253 228 }
maxter@253 229 }
maxter@354 230
maxter@372 231 /**
maxter@372 232 Base class for polymorphic non-QObjects (TBD).
maxter@372 233 */
maxter@372 234 /* package */ abstract class NonQObject : QtdObject
maxter@372 235 {
maxter@372 236 alias NonQObjectMetaClass Meta;
maxter@372 237
maxter@372 238 this(void* nativeId, QtdObjectInitFlags initFlags)
maxter@372 239 {
maxter@372 240 _flags.polymorphic = true;
maxter@372 241 super(nativeId, initFlags);
maxter@372 242 }
maxter@372 243 }
maxter@372 244
maxter@372 245 /**
maxter@372 246 Base class for QtD meta-object classes.
maxter@372 247 */
maxter@372 248 abstract class QtdMetaClass : MetaClass
maxter@372 249 {
maxter@372 250 alias QtdObject function(void* nativeId, QtdObjectInitFlags initFlags) CreateWrapper;
maxter@372 251
maxter@372 252 private void* _nativeId;
maxter@372 253 protected CreateWrapper _createWrapper;
maxter@372 254
maxter@372 255 this() {}
maxter@372 256
maxter@372 257 /**
maxter@372 258 */
maxter@372 259 @property
maxter@372 260 void* nativeId()
maxter@372 261 {
maxter@372 262 return _nativeId;
maxter@372 263 }
maxter@372 264
maxter@372 265 void construct(T)()
maxter@372 266 {
maxter@372 267 super.construct!T();
maxter@372 268 _nativeId = T.qtdNativeStaticMetaObject();
maxter@372 269 _createWrapper = &T.qtdCreateWrapper;
maxter@372 270 }
maxter@372 271
maxter@372 272 abstract QtdObject getWrapper(void* nativeId, QtdObjectInitFlags initFlags = QtdObjectInitFlags.none);
maxter@372 273 }
maxter@372 274
maxter@372 275 /**
maxter@372 276 Meta-object class for non-QObject polymorphic classes.
maxter@372 277 */
maxter@372 278 final class NonQObjectMetaClass : QtdMetaClass
maxter@372 279 {
maxter@372 280 alias typeof(this) This;
maxter@372 281 alias createImpl!This create;
maxter@372 282
maxter@372 283 @property override This next()
maxter@372 284 {
maxter@372 285 return static_cast!This(super.next);
maxter@372 286 }
maxter@372 287
maxter@372 288 @property override This firstDerived()
maxter@372 289 {
maxter@372 290 return static_cast!This(super.firstDerived);
maxter@372 291 }
maxter@372 292
maxter@372 293 override QtdObject getWrapper(void* nativeId, QtdObjectInitFlags initFlags)
maxter@372 294 {
maxter@372 295 // traverse the inheritance tree to find a matching meta-object.
maxter@372 296 // if the exact match is not found, return the closest base.
maxter@372 297 This lookUp(This mo)
maxter@372 298 {
maxter@372 299 if (!qtdTypeInfosEqual(mo.nativeId, nativeId))
maxter@372 300 {
maxter@372 301 for (auto mo2 = mo.firstDerived; mo2 !is null; mo2 = mo2.next)
maxter@372 302 {
maxter@372 303 mo2 = lookUp(mo2);
maxter@372 304 if (mo != mo2)
maxter@372 305 break;
maxter@372 306 }
maxter@372 307 }
maxter@372 308 return mo;
maxter@372 309 }
maxter@372 310
maxter@372 311 auto mo = lookUp(this);
maxter@372 312 return static_cast!NonQObject(mo._createWrapper(nativeId, initFlags));
maxter@372 313 }
maxter@372 314 }
maxter@372 315
maxter@372 316 extern (C) bool qtdTypeInfosEqual(void* info1, void* info2);
maxter@372 317
maxter@357 318 mixin(qtdExport("void", "QtdObject_delete", "void* dId",
maxter@357 319 q{
maxter@357 320 auto obj = cast(QtdObject)dId;
maxter@354 321
maxter@372 322 mixin(debugHandler("onDeletingWrapperFromNative", "dId"));
maxter@372 323
maxter@372 324 if (!obj._flags.wrapperDeleteDisabled)
maxter@357 325 {
maxter@357 326 // Avoid deleting native object twice
maxter@372 327 obj._flags.nativeDeleteDisabled = true;
maxter@357 328 delete obj;
maxter@357 329 }
maxter@357 330 }));