diff 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 diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/d2/qtd/QtdObject.d	Wed Dec 23 16:17:22 2009 +0200
@@ -0,0 +1,386 @@
+/**
+*
+*  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;
+}
\ No newline at end of file