changeset 258:1da8870e9a62 lifetime

branched for changes to object lifetime handling
author maxter
date Wed, 16 Sep 2009 14:16:33 +0000
parents 17b5e13364b7
children 515d6e1c7b10
files qt/d1/qt/QtdObject.d
diffstat 1 files changed, 265 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/qt/d1/qt/QtdObject.d	Wed Sep 16 13:56:02 2009 +0000
+++ b/qt/d1/qt/QtdObject.d	Wed Sep 16 14:16:33 2009 +0000
@@ -2,70 +2,300 @@
 *
 *  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.io.Stdout;
+import tango.core.Memory;
+debug (QtdVerbose)
+    import tango.io.Stdout;
+
 
 enum QtdObjectFlags : ubyte
 {
     none,
-    nativeOwnership           = 0x1,
-    dOwnership                = 0x2,
-    dynamicEntity             = 0x4
-    //gcManaged               = 0x4
+    // The native object will not be deleted when the wrapper is deleted
+    skipNativeDelete          = 0b0001,
+    skipDDelete               = 0b0010,
+    hasDId                    = 0b0100,
+    stackAllocated            = 0b1000
+    /+
+    // The will be deleted when is goes out of scope. Implies skipNativeDelete
+    scoped                    = 0x08
+    +/
 }
 
-package abstract class QtdObject
+class MetaObject
 {
-    protected QtdObjectFlags __flags_;
+    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 QtdMetaObject : MetaObject
+{
+    QtdObjectBase function(void* nativeId, QtdObjectFlags flags) _createWrapper;
+    
+    void construct(T : QtdObject, Concrete = T)()
+    {
+        super.construct!(T);
+        _createWrapper = &T.__createWrapper;
+    }
+}
+
+/++
+    Meta-object for polymorphic Qt classes.
++/
+final class QtdMetaObject : MetaObject
+{
+    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 _createWrapper(nativeId, flags);
+    }
+}
+
+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))
+        {
+            __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;
+        static typeof(this) __root;
+    }
+    
+    /++
+        Use this method instead of 'is' operator to check if two D objects
+        wrap the same native object.
+    +/
+    bool isSame(QtdObject other)
+    {
+        return __nativeId == other.__nativeId;
+    }
+       
     mixin SignalHandlerOps;
 
-    this(void* nativeId, QtdObjectFlags flags = QtdObjectFlags.none)
+    this(void* nativeId, QtdObjectFlags flags)
     {
-        //Stdout.formatln("Created D object {} {:x}", nativeId, flags).newline;
-        __nativeId = nativeId;
-        __flags_ = flags;
+        super (nativeId, flags);       
+        if (!(flags & QtdObjectFlags.skipNativeDelete))
+            __pin;
     }
-
-    final QtdObjectFlags __flags()
+    
+    final void __pin()
     {
-        return __flags_;
+        debug(QtdVerbose) __print("Pinning");
+        
+        __next = __root;
+        __root = this;
+        if (__next)
+            __next.__prev = this;        
     }
-
-    /+ final +/ void __setFlags(QtdObjectFlags flags, bool value)
+    
+    final void __unpin()
     {
+        debug(QtdVerbose) __print("Unpinning");
+                
+        if (__prev)
+            __prev.__next = __next;
+        else
+            __root = __next;
+        
+        if (__next)      
+            __next.__prev = __prev;
+    }
+    
+    void __nativeOwnership(bool value)
+    {       
         if (value)
-            __flags_ |= flags;
+        {
+            assert (!(__flags & QtdObjectFlags.skipNativeDelete));            
+            __flags |= QtdObjectFlags.skipNativeDelete;
+            __unpin;
+        }
         else
-            __flags_ &= ~flags;
+        {
+            assert (__flags & QtdObjectFlags.skipNativeDelete);            
+            __flags = __flags &= ~QtdObjectFlags.skipNativeDelete;
+            __pin;
+        }
     }
-
-    // COMPILER BUG: 3206
-    protected void __deleteNative()
-    {
-        assert(false);
-    }
-
+      
     ~this()
     {
-        //Stdout.formatln("Deleting D object {}", __nativeId);
-        if (!(__flags_ & QtdObjectFlags.nativeOwnership))
-        {
-            // avoid deleting D object twice.
-            //Stdout.formatln("About to delete native object {}", __nativeId);
-            __flags_ |= QtdObjectFlags.dOwnership;
-            __deleteNative;
-        }
-        //Stdout.formatln("Deleted native D object {}", __nativeId);
+        debug(QtdVerbose) __print("In QtdObject destructor");
+        
+        if (__prev || __root is this)
+            __unpin;
+    }    
+}
+
+/++
++/
+void dispose(QtdObjectBase obj)
+{
+    obj.__flags &= ~QtdObjectFlags.skipNativeDelete;
+    delete obj;
+}
+
+// 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;
     }
 }
\ No newline at end of file