diff d2/qtd/MOC.d @ 357:9784459f0750

An attempt (failed due to optlink) to improve locality of declarations exported from QtD executables Q_CLASSINFO implementation Now Qtd can be built on Windows
author Max Samukha <maxter@spambox.com>
date Wed, 02 Jun 2010 19:38:05 +0300
parents 12cec2d14e1c
children a3f5c10414f3
line wrap: on
line diff
--- a/d2/qtd/MOC.d	Tue May 25 20:14:04 2010 +0300
+++ b/d2/qtd/MOC.d	Wed Jun 02 19:38:05 2010 +0300
@@ -106,6 +106,12 @@
     */
 }
 
+struct ClassInfoDef
+{
+    string name;
+    string value;
+}
+
 FunctionDef newSlot(string sig, string args)
 {
     return FunctionDef(sig, args, Access.Public);
@@ -116,14 +122,26 @@
     return FunctionDef(sig, args, Access.Protected);
 }
 
+struct ClassDef
+{
+    string classname;
+    FunctionDef[] signalList;
+    FunctionDef[] slotList;
+    ClassInfoDef[] classInfoList;
+}
+
 struct Generator
 {
     string output;
     string[] strings;
 //    QByteArray purestSuperClass;
 //    QList<QByteArray> metaTypes;
+
+    ClassDef cdef;
 }
 
+
+
 int lengthOfEscapeSequence(string s, uint i)
 {
     if (s[i] != '\\' || i >= s.length - 1)
@@ -187,10 +205,31 @@
     }
 }
 
-string generateCode(string className, FunctionDef[] signalList, FunctionDef[] slotList)
+ClassInfoDef[] generateClassInfoDefs(T)()
 {
-    auto gen = Generator("", []);
+    ClassInfoDef[] defs;
+    alias GetAttributes!(T, "Q_CLASSINFO") classInfos;
+    // COMPILER BUG:
+    enum len = classInfos.length;
+    foreach (i, _; Repeat!(void, len))
+        defs ~= ClassInfoDef(classInfos[i].tuple[2], classInfos[i].tuple[3]);
+
+    return defs;
+}
 
+void generateClassInfos(ref Generator gen)
+{
+    if (!gen.cdef.classInfoList.length)
+        return;
+
+    gen.output ~= "\n // classinfo: key, value\n";
+
+    foreach (c; gen.cdef.classInfoList)
+        gen.output ~= format_ctfe("    ${}, ${},\n", strreg(gen, c.name), strreg(gen, c.value));
+}
+
+string generateCode(ref Generator gen)
+{
 /*    bool isQt = (cdef->classname == "Qt");
     bool isQObject = (cdef->classname == "QObject");
     bool isConstructible = !cdef->constructorList.isEmpty();
@@ -229,11 +268,11 @@
     gen.output ~= "private static const uint[] qt_meta_data = [\n";
     gen.output ~= format_ctfe("\n // content:\n");
     gen.output ~= format_ctfe("    ${},       // revision\n", 2);
-    gen.output ~= format_ctfe("    ${},       // classname\n", strreg(gen, className));
-    gen.output ~= format_ctfe("    ${}, ${}, // classinfo\n", 0, 0);
-//    index += cdef->classInfoList.count() * 2;
+    gen.output ~= format_ctfe("    ${},       // classname\n", strreg(gen, gen.cdef.classname));
+    gen.output ~= format_ctfe("    ${}, ${}, // classinfo\n", gen.cdef.classInfoList.length, gen.cdef.classInfoList.length ? index : 0);
+    index += gen.cdef.classInfoList.length * 2;
 
-    int methodCount = signalList.length + slotList.length;// + cdef->methodList.count();
+    int methodCount = gen.cdef.signalList.length + gen.cdef.slotList.length;// + cdef->methodList.count();
     gen.output ~= format_ctfe("    ${}, ${}, // methods\n", methodCount, methodCount ? index : 0);
     index += methodCount * 5;
     gen.output ~= format_ctfe("    ${}, ${}, // properties\n", propertyList.length, propertyList.length ? index : 0);
@@ -251,17 +290,17 @@
 //
 // Build classinfo array
 //
-//    generateClassInfos();
+    generateClassInfos(gen);
 
 //
 // Build signals array first, otherwise the signal indices would be wrong
 //
-    generateFunctions(gen, signalList, "signal", MethodFlags.MethodSignal);
+    generateFunctions(gen, gen.cdef.signalList, "signal", MethodFlags.MethodSignal);
 
 //
 // Build slots array
 //
-    generateFunctions(gen, slotList, "slot", MethodFlags.MethodSlot);
+    generateFunctions(gen, gen.cdef.slotList, "slot", MethodFlags.MethodSlot);
 
 //
 // Build method array
@@ -344,18 +383,6 @@
     return ret;
 }
 
-string dDeclArgs(Args...)()
-{
-    string ret;
-    foreach(i, _; Args)
-    {
-        if (i > 0)
-            ret ~= ", ";
-        ret ~= fullName!(Args[i]);
-    }
-    return ret;
-}
-
 size_t commaCount(int argCount)
 {
     size_t ret = 0;
@@ -364,7 +391,7 @@
     return ret;
 }
 
-FunctionDef[] generateFuncDefs(alias newFunc, Funcs...)()
+FunctionDef[] genFuncDefs(alias newFunc, Funcs...)()
 {
     typeof(return) res;
     enum funcsCount = Funcs.length;
@@ -446,10 +473,26 @@
     return res ~ "}\n";
 }
 
+string generateMetaInfo(T)()
+{
+    Generator gen;
+
+    gen.cdef.classname = T.stringof;
+
+    gen.cdef.slotList = genFuncDefs!(newSignal, T.signals)();
+    gen.cdef.signalList = genFuncDefs!(newSlot, T.slots)();
+    gen.cdef.classInfoList = generateClassInfoDefs!T();
+
+    generateCode(gen);
+
+    return gen.output;
+}
+
 mixin template Q_OBJECT()
 {
     import std.typetuple;
     import qtd.Marshal;
+    import std.stdio;
     import qt.core.QString; // for QStringUtil.toNative
 
 public: // required to override the outside scope protection.
@@ -460,13 +503,10 @@
     alias findSlots!(This) slots;
     alias TypeTuple!(signals, slots) methods;
 
- 
     mixin (generateSignalEmitters(signals.length));
     mixin (generateSlotAliases(slots.length));
-
-    auto signalList = generateFuncDefs!(newSignal, signals)();
-    auto slotList = generateFuncDefs!(newSlot, slots)();
-    mixin (generateCode(typeof(this).stringof, signalList, slotList));
+    //pragma(msg, generateMetaInfo!This());
+    mixin (generateMetaInfo!This());
 
     protected int qt_metacall(QMetaObject.Call _c, int _id, void **_a)
     {
@@ -490,25 +530,38 @@
     @property
     override QMetaObject metaObject() const { return staticMetaObject(); }
 
-    private static __gshared QMetaObject _staticMetaObject;
-    private static __gshared QMetaObjectNative _nativeStaticMetaObject;
+    private static
+    {
+        __gshared QMetaObject staticMetaObject_;
+        __gshared QMetaObjectNative nativeStaticMetaObject_;
+        bool staticMoInited_;
+    }
 
     @property
     static QMetaObject staticMetaObject()
     {
-        // TODO: synchronize or enable static constructors in circular modules
-        if(!_staticMetaObject)
+        // using a thread-local flag to mitigate
+        // the performance hit caused by lazy initialization
+        if(!staticMoInited_)
         {
-            alias BaseClassesTuple!(This)[0] Base;
+            synchronized(qtdMoLock)
+            {
+                if (!staticMetaObject_)
+                {
+                    alias BaseClassesTuple!(This)[0] Base;
 
-            _nativeStaticMetaObject = QMetaObjectNative(
-                Base.staticMetaObject.nativeId,
-                qt_meta_stringdata.ptr,
-                qt_meta_data.ptr, null);
+                    nativeStaticMetaObject_ = QMetaObjectNative(
+                        Base.staticMetaObject.nativeId,
+                        qt_meta_stringdata.ptr,
+                        qt_meta_data.ptr, null);
 
-            QMetaObject.create!This(&_nativeStaticMetaObject);
+                    QMetaObject.create!This(&nativeStaticMetaObject_);
+                }
+            }
+            staticMoInited_ = true;
         }
-        return _staticMetaObject;
+
+        return staticMetaObject_;
     }
 
     /*internal*/ static void setStaticMetaObject(QMetaObject m)