Mercurial > projects > qtd
view 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 |
line wrap: on
line source
/** * * Copyright: Copyright QtD Team, 2008-2009 * License: <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a> * * Copyright QtD Team, 2008-2009 * Distributed under the Boost Software License, Version 1.0. * (See accompanying file boost-license-1.0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) * */ module qt.QtdObject; import core.memory, qt.Signal, qt.Core, qt.Memory, qt.Array; struct ScopeObject(T : QtdObjectBase) { T obj; alias obj this; ~this() { if (obj.__flags & QtdObjectFlags.stackAllocated) { delete obj; } } } ScopeObject!T scopeObject(T : QtdObjectBase)(void* nativeId, QtdObjectFlags flags = QtdObjectFlags.none) { ScopeObject!T sObj; sObj.obj = T.__wrap(nativeId, cast(QtdObjectFlags)(flags | QtdObjectFlags.skipNativeDelete | QtdObjectFlags.stackAllocated)); return sObj; } class MetaObject { alias typeof(this) This; mixin SignalHandlerOps; private { MetaObject _base; ClassInfo _classInfo; } //COMPILER BUG: not accessible from QMetaObject protected { This _firstDerived; This _next; } private void addDerived(This mo) { mo._next = _firstDerived; _firstDerived = mo; } /** Next sibling on this derivation level */ final This next() { return _next; } /** Head of the linked list of derived classes */ final This firstDerived() { return _firstDerived; } // NOTE: construction is split between this non-templated constructor and 'construct' function below. this(This base) { if (base) { base.addDerived(this); _base = base; } } // TODO: can be removed when D acquires templated constructors void construct(T : Object)() { _classInfo = T.classinfo; } final This base() { return _base; } final ClassInfo classInfo() { return _classInfo; } } /** */ abstract class QtdMetaObjectBase : MetaObject { alias QtdObjectBase function(void* nativeId, QtdObjectFlags flags) CreateWrapper; private void* _nativeId; protected CreateWrapper _createWrapper; this(void* nativeId, QtdMetaObjectBase base, CreateWrapper createWrapper) { super(base); _nativeId = nativeId; _createWrapper = createWrapper; } final void* nativeId() { return _nativeId; } } /** */ final class QtdMetaObject : QtdMetaObjectBase { alias typeof(this) This; private { // TODO: optimize to use a sorted list or something // to speed up accesses. QtdObject[] _refs; } this(void* nativeId, QtdMetaObjectBase base, CreateWrapper createWrapper) { super(nativeId, base, createWrapper); } void addRef(QtdObject object) { append!CAlloc(_refs, object); } void removeRef(QtdObject object) { remove!CAlloc(_refs, object); } QtdObject wrap(void* nativeObjId, void* typeId, QtdObjectFlags flags = QtdObjectFlags.none) { if (typeId == nativeId) { // TODO: optimize foreach (r; _refs) { if (r.__nativeId == nativeObjId) return r; } } else { for (auto mo = static_cast!(This)(_firstDerived); mo; mo = static_cast!(This)(mo._next)) { if (auto obj = mo.wrap(nativeObjId, typeId, flags)) return obj; } } return static_cast!(QtdObject)(_createWrapper(nativeObjId, flags)); } } /** Inserted into any QtD object. */ /** */ enum QtdObjectFlags : ubyte { none, // The native object will not be deleted when the wrapper is deleted skipNativeDelete = 0b0000_0001, // The wrapper will not be deleted when the native object is deleted skipDDelete = 0b0000_0010, // The wrapper reference is stored in the shell hasDId = 0b0000_0100, // The wrapper is allocated on thread-local stack stackAllocated = 0b0000_1000, // is a QObject isQObject = 0b0001_0000, // The wrapper is not subject to GC pinned = 0b0010_0000 } class QtdObjectBase { // TODO: probably, __ should be replaced with qtd_, as __ are reserved by the language /// Internal members. Do not change. void* __nativeId; /// ditto QtdObjectFlags __flags; private { QtdObjectBase __prev, __next; static QtdObjectBase __root; } new (size_t size, QtdObjectFlags flags = QtdObjectFlags.none) { return flags & QtdObjectFlags.stackAllocated ? stackAlloc.alloc(size) : GC.malloc(size, GC.BlkAttr.FINALIZE); } delete (void* p) { if ((cast(typeof(this))p).__flags & QtdObjectFlags.stackAllocated) stackAlloc.free(this.classinfo.init.length); else GC.free(p); } /** Tests if the other wrapper points to the same native object. Should be always used when two objects that may have duplicate wrappers are compared for identity. */ bool __is(QtdObjectBase other) { return __nativeId == other.__nativeId; } /** Constructs the object. */ this(void* nativeId, QtdObjectFlags flags = QtdObjectFlags.none) { __nativeId = nativeId; __flags = flags; } /** Forces destruction of the native object. */ final void __dispose() { // Avoid deleting the wrapper twice __flags |= QtdObjectFlags.skipDDelete; __deleteNative; } /** Disables garbage collection for this object. */ final void __pin() { assert (!__isPinned); __next = __root; __root = this; if (__next) __next.__prev = this; } /** Enables garbage collection for this object. */ final void __unpin() { assert (__isPinned); if (__prev) { __prev.__next = __next; __prev = null; } else __root = __next; } /** */ void __ownership(QtdOwnership native) { switch(own) { case QtdOwnership.cpp: if (!__isPinned) __pin; break; case QtdOwnership.cpp: if(!__isPinned) __pin; break; case QtdOwnership.def: assert(false, "Not implemented"); if (!(__flags & QtdObjectFlags.hasDId)) __pin; default: assert(false); } } /** Returns true if garbage collection for this object is disabled. */ final bool __isPinned() { return __prev || __root is this; } // COMPILER BUG: 3206 protected void __deleteNative() { assert(false); } ~this() { if (!(__flags & QtdObjectFlags.skipNativeDelete)) __dispose; } } /** Base class for non-QObjects. */ abstract class QtdObject : QtdObjectBase { alias typeof(this) This; // TODO: must be abstract QtdMetaObject metaObject() { return null; } /** Constructs the object. */ this(void* nativeId, QtdObjectFlags flags = QtdObjectFlags.none) { super(nativeId, flags); if (!(__flags & QtdObjectFlags.canHaveDups) && !(__flags & QtdObjectFlags.hasDId)) metaObject.addRef(this); } ~this() { if (!(__flags & QtdObjectFlags.canHaveDups) && !(__flags & QtdObjectFlags.hasDId)) metaObject.removeRef(this); } mixin SignalHandlerOps; } // Called from shell destructors extern(C) void qtd_delete_d_object(void* dId) { auto obj = cast(QtdObjectBase)dId; if (!(obj.__flags & QtdObjectFlags.skipDDelete)) { // Avoid deleting native object twice obj.__flags |= QtdObjectFlags.skipNativeDelete; delete obj; } } extern(C) void qtd_ownership(void* dId, QtdOwnership own) { auto obj = cast(QtdObjectBase)dId; obj.__ownership = own; }