changeset 364:a084e2df3776

Preparing for non-QObject meta-objects. Now meta-objects for static types can be uniformly accessed using meta!T
author Max Samukha <maxter@maxter.com>
date Fri, 11 Jun 2010 12:16:09 +0300
parents 3b0545d4d479
children 958e8b9a89bd
files d2/qt/core/QMetaObject.d d2/qtd/MOC.d d2/qtd/meta/Compiletime.d d2/qtd/meta/Runtime.d generator/dgenerator.cpp generator/typesystem_core-java.java
diffstat 6 files changed, 199 insertions(+), 163 deletions(-) [+]
line wrap: on
line diff
--- a/d2/qt/core/QMetaObject.d	Thu Jun 10 00:57:32 2010 +0300
+++ b/d2/qt/core/QMetaObject.d	Fri Jun 11 12:16:09 2010 +0300
@@ -13,11 +13,11 @@
     std.typetuple,
     std.c.stdlib;
 
-class QMetaArgument : Meta
+class QMetaArgument : MetaBase
 {
 }
 
-class QMetaMethod : Meta
+class QMetaMethod : MetaBase
 {
     alias typeof(this) This;
 
@@ -84,9 +84,31 @@
     }
 }
 
-class MetaObject : MetaType
+/**
+    Base class for QtD meta-classes.
+ */
+abstract class QtdMetaClass : MetaClass
 {
-    MetaObject _base;
+private:
+    void* nativeId_;
+
+    this() {}
+
+public:
+
+    /**
+     */
+    @property
+    void* nativeId()
+    {
+        return nativeId_;
+    }
+
+    /* internal */ void construct(T)()
+    {
+        super.construct!T();
+        nativeId_ = T.qtd_nativeMetaObject;
+    }
 }
 
 struct QMetaObjectNative
@@ -99,12 +121,10 @@
 
 class QMetaException : Exception { this(string msg) { super(msg); } }
 
-final class QMetaObject
+final class QMetaObject : QtdMetaClass
 {
     alias typeof(this) This;
 
-    private this() {}
-
     enum Call
     {
         InvokeMetaMethod,
@@ -121,40 +141,13 @@
 
     private
     {
-        QMetaObjectNative* _nativeId;
-        QMetaObject _base; // super class
-        QMetaObject _firstDerived; // head of the linked list of derived classes
-        QMetaObject _next; // next sibling on this derivation level
         QMetaMethod[] _methods;
-        ClassInfo _classInfo;
-
         QObject function(void* nativeId) _createWrapper;
     }
 
-    private void addDerived(QMetaObject mo)
-    {
-        mo._next = _firstDerived;
-        _firstDerived = mo;
-    }
-
-    // ctor
-    void construct(T : QObject)(void* nativeId)
+    void construct(T : QObject)()
     {
-        alias BaseClassesTuple!(T)[0] Base;
-        This base;
-        static if (is(Base : QObject))
-            base = Base.staticMetaObject;
-
-        _nativeId = cast(QMetaObjectNative*)nativeId;
-        T.setStaticMetaObject(this);
-
-        if (base)
-        {
-            base.addDerived(this);
-            _base = base;
-        }
-        _classInfo = T.classinfo;
-
+        super.construct!T();
 
         static if (isQtType!T)
         {
@@ -171,9 +164,11 @@
 
             T._populateMetaInfo;
         }
+
         // create run time meta-objects for user-defined signals and slots
         else static if (is(typeof(T.methods)))
         {
+            alias BaseClassesTuple!(T)[0] Base;
             int index = Base.staticMetaObject().methodCount();
 
             static if (T.signals.length)
@@ -196,35 +191,41 @@
         }
     }
 
-    // new
-    static This create(T : QObject)(void* nativeId)
+    /* internal */ alias createImpl!This create;
+
+    /**
+     */
+    @property
+    override This base()
     {
-        auto m = new This();
-        m.construct!T(nativeId);
-        return m;
+        return super.base;
     }
 
-    /++
-    +/
-    QMetaObject base()
+    /**
+     */
+    @property
+    override This firstDerived()
     {
-        return _base;
+        return super.firstDerived;
     }
 
-    /++
-    +/
-    QMetaObjectNative* nativeId()
+    /**
+     */
+    @property
+    override This next()
     {
-        return _nativeId;
+        return super.next;
     }
 
-    /++
-    +/
-    ClassInfo classInfo()
+    /**
+     */
+    @property
+    override QMetaObjectNative* nativeId()
     {
-        return _classInfo;
+        return cast(QMetaObjectNative*)super.nativeId;
     }
 
+    @property
     const (QMetaMethod[]) methods()
     {
         return _methods;
@@ -240,8 +241,8 @@
         foreach (method; _methods)
             if (method.signature == slot)
                 return method;
-        if (_base)
-            return _base.lookUpMethod(slot);
+        if (base)
+            return base.lookUpMethod(slot);
         else
             return null;
     }
@@ -251,8 +252,8 @@
         foreach (method; _methods)
             if (method.signature == signal && cast(QMetaSignal)method)
                 return cast(QMetaSignal)method;
-        if (_base)
-            return _base.lookUpSignal(signal);
+        if (base)
+            return base.lookUpSignal(signal);
         else
             return null;
     }
@@ -263,8 +264,8 @@
         foreach (method; _methods)
             if (method.name == methodName)
                 result ~= method;
-        if (_base)
-            result ~= _base.lookUpMethodOverloads(methodName);
+        if (base)
+            result ~= base.lookUpMethodOverloads(methodName);
         return result;
     }
 
@@ -274,8 +275,8 @@
         foreach (method; _methods)
             if (method.name == signalName && cast(QMetaSignal)method)
                 result ~= cast(QMetaSignal)method;
-        if (_base)
-            result ~= _base.lookUpSignalOverloads(signalName);
+        if (base)
+            result ~= base.lookUpSignalOverloads(signalName);
         return result;
     }
 
@@ -283,9 +284,9 @@
     {
         assert (moIds.length >= 1);
 
-        for (auto mo = _firstDerived; mo !is null; mo = mo._next)
+        for (auto mo = firstDerived; mo !is null; mo = mo.next)
         {
-            if (mo._nativeId == moIds[0])
+            if (mo.nativeId == moIds[0])
             {
                 if (moIds.length == 1) // exact match found
                     return mo;
@@ -308,8 +309,9 @@
             result = cast(QObject)qtd_get_d_qobject(nativeObjId);
             if (!result)
             {
+                auto nId = nativeId;
                 auto moId = qtd_QObject_metaObject(nativeObjId);
-                if (_nativeId == moId)
+                if (nId == moId)
                      result = _createWrapper(nativeObjId);
                 else
                 {
@@ -321,7 +323,7 @@
                     {
                         tmp = qtd_QMetaObject_superClass(tmp);
                         assert(tmp);
-                        if (tmp == _nativeId)
+                        if (tmp == nId)
                             break;
                         moCount++;
                     }
@@ -359,12 +361,12 @@
 
     int indexOfMethod_Cpp(string method)
     {
-        return qtd_QMetaObject_indexOfMethod(_nativeId, toStringz(method));
+        return qtd_QMetaObject_indexOfMethod(nativeId, toStringz(method));
     }
 
     int methodCount()
     {
-        return qtd_QMetaObject_methodCount(_nativeId);
+        return qtd_QMetaObject_methodCount(nativeId);
     }
 
     static void connectImpl(QObject sender, string signalString, QObject receiver, string methodString, int type)
--- a/d2/qtd/MOC.d	Thu Jun 10 00:57:32 2010 +0300
+++ b/d2/qtd/MOC.d	Fri Jun 11 12:16:09 2010 +0300
@@ -490,10 +490,12 @@
 
 mixin template Q_OBJECT()
 {
-    import std.typetuple;
-    import qtd.Marshal;
-    import std.stdio;
-    import qt.core.QString; // for QStringUtil.toNative
+    import
+        std.typetuple,
+        qtd.meta.Runtime,
+        qtd.Marshal,
+        qt.core.QString,
+        std.stdio;
 
 public: // required to override the outside scope protection.
 
@@ -530,43 +532,24 @@
     @property
     override QMetaObject metaObject() const { return staticMetaObject(); }
 
-    private static
-    {
-        __gshared QMetaObject staticMetaObject_;
-        __gshared QMetaObjectNative nativeStaticMetaObject_;
-        bool staticMoInited_;
-    }
-
     @property
     static QMetaObject staticMetaObject()
     {
-        // using a thread-local flag to mitigate
-        // the performance hit caused by lazy initialization
-        if(!staticMoInited_)
-        {
-            synchronized(qtdMoLock)
-            {
-                if (!staticMetaObject_)
-                {
-                    alias BaseClassesTuple!(This)[0] Base;
-
-                    nativeStaticMetaObject_ = QMetaObjectNative(
-                        Base.staticMetaObject.nativeId,
-                        qt_meta_stringdata.ptr,
-                        qt_meta_data.ptr, null);
-
-                    QMetaObject.create!This(&nativeStaticMetaObject_);
-                }
-            }
-            staticMoInited_ = true;
-        }
-
-        return staticMetaObject_;
+        return meta!This;
     }
 
-    /*internal*/ static void setStaticMetaObject(QMetaObject m)
+    @property static void* qtd_nativeMetaObject()
     {
-        staticMetaObject_ = m;
+        __gshared static QMetaObjectNative nativeMo;
+        if (!nativeMo.data)
+        {
+            alias BaseClassesTuple!(This)[0] Base;
+            nativeMo = QMetaObjectNative(
+                Base.staticMetaObject.nativeId,
+                qt_meta_stringdata.ptr,
+                qt_meta_data.ptr, null);
+        }
+        return &nativeMo;
     }
 }
 
--- a/d2/qtd/meta/Compiletime.d	Thu Jun 10 00:57:32 2010 +0300
+++ b/d2/qtd/meta/Compiletime.d	Fri Jun 11 12:16:09 2010 +0300
@@ -6,11 +6,12 @@
 module qtd.meta.Compiletime;
 
 import
-    std.traits,
     std.conv,
     std.variant,
     std.typetuple;
 
+public import std.traits;
+
 import std.string : startsWith;
 
 /**
--- a/d2/qtd/meta/Runtime.d	Thu Jun 10 00:57:32 2010 +0300
+++ b/d2/qtd/meta/Runtime.d	Fri Jun 11 12:16:09 2010 +0300
@@ -8,6 +8,7 @@
 //and leave switch dispatch only in C interface
 
 import
+    qtd.Core,
     qtd.meta.Compiletime,
 
     std.typetuple,
@@ -87,13 +88,13 @@
     }
 }
 
-abstract class Meta
+abstract class MetaBase
 {
     alias typeof(this) This;
 
     string name;
     MetaAttribute[] attributes;
-    Meta[] members;
+    MetaBase[] members;
 
     template createImpl(M : This)
     {
@@ -153,7 +154,7 @@
     }
 }
 
-abstract class MetaType : Meta
+abstract class MetaType : MetaBase
 {
 }
 
@@ -164,7 +165,63 @@
 class MetaClass : MetaAggregate
 {
     alias typeof(this) This;
-    alias createImpl!This create;
+
+private:
+    This base_;
+    This firstDerived_;
+    This next_;
+    TypeInfo_Class classInfo_;
+
+    this() {}
+
+public:
+    /**
+        Returns the meta-object of the base class.
+     */
+    @property
+    This base()
+    {
+        return base_;
+    }
+
+    /**
+        Returns next meta-object on this level of the derivation hierarchy.
+     */
+    @property
+    This next()
+    {
+        return next_;
+    }
+
+    /**
+        Returns meta-object of the first derived class.
+     */
+    @property
+    This firstDerived()
+    {
+        return firstDerived_;
+    }
+
+    /**
+        D class info.
+     */
+    @property
+    TypeInfo_Class classInfo()
+    {
+        return classInfo_;
+    }
+
+    /* internal */ alias createImpl!This create;
+
+    /* internal */ void construct(T : Object)()
+    {
+        static if (!is(T == Object))
+        {
+            alias BaseClassesTuple!(T)[0] Base;
+            base_ = meta!Base;
+        }
+        classInfo_ = T.classinfo;
+    }
 }
 
 class MetaStruct : MetaAggregate
@@ -174,24 +231,21 @@
 }
 
 @property
-auto meta(alias symbol, M : Meta)()
+auto meta(alias symbol, M : MetaBase)()
 {
-    __gshared static M m;
+    __gshared static M sharedM;
+    static M m;
 
+    if (!m)
     {
-        lock.reader.lock;
-        scope(exit)
-            lock.reader.unlock;
-        if (m)
-            return m;
+        synchronized(qtdMoLock)
+        {
+            if (!sharedM)
+                sharedM = M.create!symbol;
+        }
+        m = sharedM;
     }
 
-    lock.writer.lock;
-    scope(exit)
-        lock.writer.unlock;
-
-    if (!m)
-        m = M.create!symbol;
     return m;
 }
 
@@ -199,8 +253,8 @@
 @property
 auto meta(T)()
 {
-    static if (is(typeof(T.staticMetaObject)))
-        return T.staticMetaObject;
+    static if (is(T.Meta)) // If the type defines a meta-class - use that.
+        return meta!(T, T.Meta);
     else static if (is(T == class))
         return meta!(T, MetaClass);
     else static if (is(T == struct))
--- a/generator/dgenerator.cpp	Thu Jun 10 00:57:32 2010 +0300
+++ b/generator/dgenerator.cpp	Fri Jun 11 12:16:09 2010 +0300
@@ -1958,8 +1958,9 @@
         if (d_class->isQObject()) {
             s << "public import qtd.Signal;" << endl
               << "public import qtd.MOC;" << endl
-              << "public import qtd.Traits;" << endl
-              << "public import qt.core.QMetaObject;" << endl;
+              << "public import qtd.Traits;" << endl              
+              << "public import qt.core.QMetaObject;" << endl
+              << "import qtd.meta.Runtime;" << endl;
 
             if (d_class->name() != "QObject")
                 s << "public import qt.core.QObject;" << endl;
@@ -2568,11 +2569,6 @@
         if (d_class->typeEntry()->isValue())
             s << INDENT << d_class->name() << ".QTypeInfo.init();" << endl;
 
-        if (d_class->isQObject()) {
-            // ensure meta-object is created at static construction
-            s << INDENT << d_class->name() << ".staticMetaObject();" << endl;
-        }
-
         if (cpp_shared && d_class->generateShellClass()) {
 
             AbstractMetaFunction::Options opts(AbstractMetaFunction::DeclaringClass | AbstractMetaFunction::NoExternNamespace);
@@ -2694,7 +2690,7 @@
 
 void DGenerator::writeQObjectFreeFunctions(QTextStream &s, const AbstractMetaClass *d_class)
 {
-    s << "extern(C) QMetaObjectNative* qtd_" << d_class->name() << "_staticMetaObject();" << endl << endl
+    s << "extern(C) void* qtd_" << d_class->name() << "_staticMetaObject();" << endl << endl
       << "extern(C) void qtd_" << d_class->name() << "_createEntity(void* nativeId, void* dId);" <<  endl << endl
       << "extern(C) int qtd_" << d_class->name() << "_qt_metacall(void *nativeId, QMetaObject.Call _c, int _id, void **_a);" << endl;
 
@@ -2761,31 +2757,29 @@
           << "    }" << endl << endl;
     }
 
-    s << "    private static __gshared QMetaObject staticMetaObject_;" << endl
-      << "    protected static void setStaticMetaObject(QMetaObject m) {" << endl
-      << "        staticMetaObject_ = m;" << endl
-      << "    }" << endl << endl
+    s << "    @property static void* qtd_nativeMetaObject() {" << endl
+      << "          return qtd_" << d_class->name() << "_staticMetaObject();" << endl
+      << "    }"
 
       << "    @property QMetaObject metaObject() {" << endl
-      << "        return staticMetaObject_;" << endl
+      << "        return staticMetaObject;" << endl
       << "    }" << endl << endl
 
       << "    @property static QMetaObject staticMetaObject() {" << endl
-      << "        if (!staticMetaObject_)" << endl
-      << "            QMetaObject.create!(typeof(this))(qtd_" << d_class->name() << "_staticMetaObject());" << endl
-      << "        return staticMetaObject_;" << endl
+      << "        return meta!(typeof(this));" << endl
       << "    }" << endl << endl
 
       << "    static " << d_class->name() << " __getObject(void* nativeId) {" << endl
-      << "        return static_cast!(" << d_class->name() << ")(staticMetaObject_.getObject(nativeId));" << endl
+      << "        return static_cast!(" << d_class->name() << ")(staticMetaObject.getObject(nativeId));" << endl
       << "    }" << endl << endl
 
-      << "    /* internal */ static void __createEntity(void* nativeId, void* dId) {" << endl
+      << "    static void __createEntity(void* nativeId, void* dId) {" << endl
       << "        return qtd_" << d_class->name() << "_createEntity(nativeId, dId);" << endl
       << "    }" << endl << endl
 
-      << "    /* internal */ static void _populateMetaInfo() {" << endl
-      << "        int index;" << endl << endl;
+      << "    static void _populateMetaInfo() {" << endl
+      << "        int index;" << endl
+      << "        auto mo = staticMetaObject;" << endl << endl;
 
     AbstractMetaFunctionList signal_funcs = signalFunctions(d_class, false);
 
@@ -2797,8 +2791,8 @@
       do // need this to look for default arguments and generate extra signatures
       {
           AbstractMetaFunction *fn = signal_funcs.at(i);
-    s << "        index = staticMetaObject_.indexOfMethod_Cpp(__signalSignatures[" << staticId << "]);" << endl
-    << "        staticMetaObject_.addMethod(new QMetaSignal(signature!(";
+    s << "        index = mo.indexOfMethod_Cpp(__signalSignatures[" << staticId << "]);" << endl
+      << "        mo.addMethod(new QMetaSignal(signature!(";
           writeMetaMethodArguments(s, fn, j);
     s << ")(\"" << fn->name() << "\"), index));" << endl << endl;
           AbstractMetaArgumentList args = fn->arguments();
@@ -2819,8 +2813,8 @@
       do // need this to look for default arguments and generate extra signatures
       {
           AbstractMetaFunction *fn = slot_funcs.at(i);
-    s << "        index = staticMetaObject_.indexOfMethod_Cpp(__slotSignatures[" << staticId << "]);" << endl
-    << "        staticMetaObject_.addMethod(new QMetaSlot(signature!(";
+    s << "        index = mo.indexOfMethod_Cpp(__slotSignatures[" << staticId << "]);" << endl
+      << "        mo.addMethod(new QMetaSlot(signature!(";
           writeMetaMethodArguments(s, fn, j);
     s << ")(\"" << fn->name() << "\"), index));" << endl << endl;
           AbstractMetaArgumentList args = fn->arguments();
--- a/generator/typesystem_core-java.java	Thu Jun 10 00:57:32 2010 +0300
+++ b/generator/typesystem_core-java.java	Fri Jun 11 12:16:09 2010 +0300
@@ -45,10 +45,12 @@
 import qt.core.*;
 
 class QObject___ extends QObject {
-    
+
+    alias QMetaObject Meta;
+
     /* TODO: test whether the linked list is really a better solution
     public bool __stackAllocated = false;
-    
+
     new(size_t size, void* p = null)
     {
         if (!p)
@@ -72,23 +74,23 @@
         }
     }
     */
-    
+
     private
     {
         static QObject __root;
         QObject __next;
         QObject __prev;
     }
-/*    
+/*
     override void onSignalHandlerCreated(ref SignalHandler sh)
     {
         sh.signalEvent = &onSignalEvent;
     }
-    
+
     private void onSignalEvent(int signalId, SignalEventId event)
     {
         stringz signature;
-        signalSignature(signalId, signature);        
+        signalSignature(signalId, signature);
         if (signature)
         {
             switch (event)
@@ -111,11 +113,11 @@
             __prev.__next = __next;
         else
             __root = __next;
-        
-        if (__next)      
-            __next.__prev = __prev;        
+
+        if (__next)
+            __next.__prev = __prev;
     }
-    
+
     /**
     */
     T findChild(T : QObject = QObject)(string name = null)
@@ -125,23 +127,23 @@
             auto tmp = cast(T)obj;
             if (tmp && (!name.length || tmp.objectName == name))
                 return tmp;
-            
+
             tmp = obj.findChild!(T)(name);
             if (tmp)
                 return tmp;
         }
-        
+
         return null;
     }
-    
+
     /**
     */
     T[] findChildren(T : QObject = QObject)(string name = null)
     {
         T[] result;
-        
+
         void find(QObject[] objects)
-        {        
+        {
             foreach (obj; objects)
             {
                 auto tmp = cast(T)obj;
@@ -150,11 +152,11 @@
                 find(obj.children);
             }
         }
-        
+
         find(children);
         return result;
     }
-    
+
     static void connect(QObject sender, string signal, QObject receiver, string method, int type = 0)
     {
         QMetaObject.connectImpl(sender, signal, receiver, method, type);