Mercurial > projects > qtd
view 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 |
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> * Authors: Max Samukha, Eldar Insafutdinov * * 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 qt.Signal; import tango.core.Memory; debug (QtdVerbose) import tango.io.Stdout; enum QtdObjectFlags : ubyte { none, // The native object will not be deleted when the wrapper is deleted skipNativeDelete = 0b0_0001, // The wrapper will not be deleted when the native object is deleted skipDDelete = 0b0_0010, // D object reference is stored in the shell hasDId = 0b0_0100, // The wrapper is allocated on thread-local stack and destroyed at the end of the scope stackAllocated = 0b0_1000 // It is a QObject isQObject = 0b1_0000 } class MetaObject { alias typeof(this) This; 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 { QtdObjectBase function(void* nativeId, QtdObjectFlags flags) _createWrapper; this(QtdMetaObjectBase base) { super(base); } void construct(T : QtdObject)() { super.construct!(T); _createWrapper = &T.__createWrapper; } } final class QtdMetaObject : QtdMetaObjectBase { alias typeof(this) This; private void* _typeId; this(void* typeId, QtdMetaObject base) { super(base); _typeId = typeId; } QtdObject wrap(void* nativeId, void* typeId, QtdObjectFlags flags = QtdObjectFlags.skipNativeDelete) { if (typeId == _typeId) { /+ if (auto p = nativeId in _nativeToDMap) return *p; +/ } else { for (auto mo = static_cast!(This)(_firstDerived); mo; mo = static_cast!(This)(mo._next)) { if (auto obj = mo.wrap(nativeId, typeId, flags)) return obj; } } return static_cast!(QtdObject)(_createWrapper(nativeId, flags)); } } class IdMappings { private void* _data; this() { } void add(void* nativeId, void* dId) { } void remove(void* dId) { } void* opIndex[void* nativeId] { } ~this() { free(_data); } } abstract class QtdObjectBase { alias typeof(this) This; void* __nativeId; QtdObjectFlags __flags; 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(This)p).__flags & QtdObjectFlags.stackAllocated) __stackAlloc.free(this.classinfo.init.length); else GC.free(p); } this(void* nativeId, QtdObjectFlags flags = QtdObjectFlags.none) { __nativeId = nativeId; __flags = flags; debug(QtdVerbose) __print("D wrapper constructed"); } debug(QtdVerbose) { void __print(string msg) { Stdout.formatln("{} (native: {}, D: {}, flags 0b{:b})", msg, __nativeId, cast(void*)this, __flags); } } protected void __deleteNative() { assert(false, "Cannot delete native " ~ this.classinfo.name ~ " because it has no public destructor"); } ~this() { debug(QtdVerbose) __print("In QtdObjectBase destructor"); if (!(__flags & QtdObjectFlags.skipNativeDelete)) { // Avoid deleting the wrapper twice __flags |= QtdObjectFlags.skipDDelete; debug(QtdVerbose) __print("About to call native delete"); __deleteNative; } } } // Base class for by-reference objects abstract class QtdObject : QtdObjectBase { private { typeof(this) __next, __prev; ubyte __nativeRef_; static typeof(this) __root; } mixin SignalHandlerOps; this(void* nativeId, QtdObjectFlags flags) { super (nativeId, flags); if (!(flags & QtdObjectFlags.isQObject) && !(flags & QtdObjectFlags.hasDId)) __addIdMapping; } void __addIdMapping() {} void __removeIdMapping() {} final void __nativeRef() { assert (__nativeRef_ < 255); if (!__nativeRef_) { __next = __root; __root = this; if (__next) __next.__prev = this; } __nativeRef_++; debug(QtdVerbose) __print("Native ref incremented"); } final void __nativeDeref() { assert (__nativeRef > 0); __nativeRef_--; if (!__nativeRef_) { if (__prev) __prev.__next = __next; else __root = __next; if (__next) __next.__prev = __prev; } debug(QtdVerbose) __print("Native ref decremented"); } ~this() { if (!(__flags & QtdObjectFlags.isQObject) && !(__flags & QtdObjectFlags.hasDId)) __removeMapping; if (__nativeRef_) { if (__nativeRef_ > 1) { debug(QtdVerbose) __print("Native ref is greater then 1 when deleting the object"); __nativeRef_ = 1; } __nativeDeref; } } } // Called from shell destructors extern(C) void qtd_delete_d_object(void* dId) { auto obj = cast(QtdObject)dId; debug(QtdVerbose) obj.__print("In qtd_delete_d_object"); if (!(obj.__flags & QtdObjectFlags.skipDDelete)) { // Avoid deleting native object twice obj.__flags |= QtdObjectFlags.skipNativeDelete; delete obj; } } extern(C) void qtd_native_ref(void* dId) { (cast(QtdObject)dId).__nativeRef; } extern(C) void qtd_native_deref(void* dId) { (cast(QtdObject)dId).__nativeDeref; }