[Kde-bindings] KDE/kdebindings

Arno Rehn kde at arnorehn.de
Tue Mar 10 16:34:16 UTC 2009


SVN commit 937860 by arnorehn:

* Get rid of application_terminated checks in methodcall.cpp and make the
  application cleanup properly. The problem was WeakReference.IsValid being
  false when the application was in the process of shutting down, even though
  the target object was still there. When shutting down, convert weak refs to
  strong refs and check for objects in the global reference map.
  Only thing that doesn't work correctly is QCoreApplication and subclasses.
  It's expected to be deleted as the last Qt object and a bug in QApplication
  is preventing its deletion in an atexit() function. Work around that by not
  calling it's destructor for now.

CCMAIL: kde-bindings at kde.org



 M  +11 -0     csharp/qyoto/ChangeLog  
 M  +1 -1      csharp/qyoto/core/QCoreApplication.cs  
 M  +4 -1      csharp/qyoto/gui/QApplication.cs  
 M  +5 -0      csharp/qyoto/src/Qyoto.cs  
 M  +30 -1     csharp/qyoto/src/SmokeMarshallers.cs  
 M  +5 -5      csharp/qyoto/src/handlers.cpp  
 M  +8 -5      csharp/qyoto/src/methodcall.cpp  
 M  +3 -0      csharp/qyoto/src/qyoto.cpp  
 M  +1 -1      kalyptus/kalyptusCxxToKimono.pm  


--- trunk/KDE/kdebindings/csharp/qyoto/ChangeLog #937859:937860
@@ -1,3 +1,14 @@
+2009-02-10  Arno Rehn  <arno at arnorehn.de>
+	* Get rid of application_terminated checks in methodcall.cpp and make the
+	  application cleanup properly. The problem was WeakReference.IsValid being
+	  false when the application was in the process of shutting down, even though
+	  the target object was still there. When shutting down, convert weak refs to
+	  strong refs and check for objects in the global reference map.
+	  Only thing that doesn't work correctly is QCoreApplication and subclasses.
+	  It's expected to be deleted as the last Qt object and a bug in QApplication
+	  is preventing its deletion in an atexit() function. Work around that by not
+	  calling it's destructor for now.
+
 2009-02-23  Arno Rehn  <arno at arnorehn.de>
 	* Apply a patch from Eric Butler: Fix Qyoto.GetCPPEnumValue() to return the
 	  correct value.
--- trunk/KDE/kdebindings/csharp/qyoto/core/QCoreApplication.cs #937859:937860
@@ -79,7 +79,7 @@
         }
         public static int Exec() {
             int result = (int) staticInterceptor.Invoke("exec", "exec()", typeof(int));
-            Qyoto.SetApplicationTerminated();
+            Qyoto.Cleanup();
             return result;
         }
         public static void ProcessEvents(uint flags) {
--- trunk/KDE/kdebindings/csharp/qyoto/gui/QApplication.cs #937859:937860
@@ -145,6 +145,9 @@
         public static void SetColorSpec(int arg1) {
             staticInterceptor.Invoke("setColorSpec$", "setColorSpec(int)", typeof(void), typeof(int), arg1);
         }
+        public static void SetGraphicsSystem(string arg1) {
+            staticInterceptor.Invoke("setGraphicsSystem$", "setGraphicsSystem(const QString&)", typeof(void), typeof(string), arg1);
+        }
         public static QCursor OverrideCursor() {
             return (QCursor) staticInterceptor.Invoke("overrideCursor", "overrideCursor()", typeof(QCursor));
         }
@@ -276,7 +279,7 @@
         }
         public static new int Exec() {
             int result = (int) staticInterceptor.Invoke("exec", "exec()", typeof(int));
-            Qyoto.SetApplicationTerminated();
+            Qyoto.Cleanup();
             return result;
         }
         public static void CloseAllWindows() {
--- trunk/KDE/kdebindings/csharp/qyoto/src/Qyoto.cs #937859:937860
@@ -285,6 +285,11 @@
 		/// This hashtable has the class types as keys, and QMetaObjects as values
 		static Dictionary<Type, QMetaObject> metaObjects = new Dictionary<Type, QMetaObject> ();
 		
+		public static void Cleanup() {
+			SmokeMarshallers.ConvertRefs();
+			SetApplicationTerminated();
+		}
+		
 		public static uint GetCPPEnumValue(string c, string value) {
 			Type t = Type.GetType("Qyoto." + c, false);
 			if (t == null) {
--- trunk/KDE/kdebindings/csharp/qyoto/src/SmokeMarshallers.cs #937859:937860
@@ -363,7 +363,7 @@
 		public static void MapPointer(IntPtr ptr, IntPtr instancePtr, bool createGlobalReference) {
 			lock (pointerMap) {
 				Object instance = ((GCHandle) instancePtr).Target;
-				WeakReference weakRef = new WeakReference(instance);
+				WeakReference weakRef = new WeakReference(instance, true);
 				pointerMap[ptr] = weakRef;
 #if DEBUG
 				if ((QDebug.DebugChannel() & QtDebugChannel.QTDB_GC) != 0) {
@@ -411,6 +411,7 @@
 		// of a Qyoto class and therefore could have custom slots or overriden methods
 		public static IntPtr GetInstance(IntPtr ptr, bool allInstances) {
 			WeakReference weakRef;
+			object strongRef;
 			if (!pointerMap.TryGetValue(ptr, out weakRef)) {
 #if DEBUG
 				if (	(QDebug.DebugChannel() & QtDebugChannel.QTDB_GC) != 0
@@ -440,6 +441,24 @@
 				GCHandle instanceHandle = GCHandle.Alloc(weakRef.Target);
 #endif
 				return (IntPtr) instanceHandle;
+			} else if (Environment.HasShutdownStarted && globalReferenceMap.TryGetValue(ptr, out strongRef)) {
+#if DEBUG
+				if (	(QDebug.DebugChannel() & QtDebugChannel.QTDB_GC) != 0
+						&& QDebug.debugLevel >= DebugLevel.Extensive ) 
+				{
+					Console.WriteLine("GetInstance() strongRef 0x{0:x8} -> {1}", (int) ptr, strongRef);
+				}
+#endif
+				if (!allInstances && IsSmokeClass(strongRef.GetType())) {
+					return IntPtr.Zero;
+				} 
+
+#if DEBUG
+				GCHandle instanceHandle = DebugGCHandle.Alloc(strongRef);
+#else
+				GCHandle instanceHandle = GCHandle.Alloc(strongRef);
+#endif
+				return (IntPtr) instanceHandle;
 			} else {
 #if DEBUG
 				if (	(QDebug.DebugChannel() & QtDebugChannel.QTDB_GC) != 0
@@ -453,6 +472,16 @@
 			}
 		}
 
+		// converts weak references to strong references so they are still available
+		// when the application is shutting down.
+		public static void ConvertRefs() {
+			foreach (KeyValuePair<IntPtr, WeakReference> pair in pointerMap) {
+				if (!pair.Value.IsAlive)
+					continue;
+				globalReferenceMap[pair.Key] = pair.Value.Target;
+			}
+		}
+
 		private class SmokeClassData {
 			public string className;
 			public ConstructorInfo constructorInfo;
--- trunk/KDE/kdebindings/csharp/qyoto/src/handlers.cpp #937859:937860
@@ -1043,10 +1043,10 @@
 		}
 
 		if(m->type().isStack()) {
-// 		    o->allocated = true;
-			// Keep a mapping of the pointer so that it is only wrapped once
-		    mapPointer(obj, o, o->classId, 0);
+		    o->allocated = true;
 		}
+		// Keep a mapping of the pointer so that it is only wrapped once
+		mapPointer(obj, o, o->classId, 0);
 		
 		m->var().s_class = obj;
 	}
@@ -1455,9 +1455,9 @@
 
 		if (m->type().isStack()) {
 		    o->allocated = true;
-			// Keep a mapping of the pointer so that it is only wrapped once
-		    mapPointer(obj, o, o->classId, 0);
 		}
+		// Keep a mapping of the pointer so that it is only wrapped once
+		mapPointer(obj, o, o->classId, 0);
 		
 		m->var().s_class = obj;
 	}
--- trunk/KDE/kdebindings/csharp/qyoto/src/methodcall.cpp #937859:937860
@@ -26,10 +26,10 @@
 		_o = (smokeqyoto_object*) (*GetSmokeObject)(_target);
 		if (_o != 0 && _o->ptr != 0) {
 			if (	isDestructor() 
-					&& (!_o->allocated || IsContainedInstance(_o) || application_terminated) ) 
+					&& (!_o->allocated || IsContainedInstance(_o)
+					    || smoke->isDerivedFromByName(smoke->className(_o->classId), "QCoreApplication")) )
 			{
 				_called = true;
-// 				_o->allocated = false;
 			}
 		} else {
 			// not a constructor, not static, pointer invalid -> object already destroyed
@@ -96,9 +96,12 @@
 		(*SetSmokeObject)(_target, _o);
 		mapPointer(_target, _o, _o->classId, 0);
 	} else if (isDestructor()) {
-		unmapPointer(_o, _o->classId, 0);
-		(*SetSmokeObject)(_target, 0);
-		free_smokeqyoto_object(_o);
+		void *check = (*GetSmokeObject)(_target);
+		if (check) {
+			unmapPointer(_o, _o->classId, 0);
+			(*SetSmokeObject)(_target, 0);
+			free_smokeqyoto_object(_o);
+		}
 	} else {
 		Qyoto::MethodReturnValue r(_smoke, _method, _stack, _retval);
 	}
--- trunk/KDE/kdebindings/csharp/qyoto/src/qyoto.cpp #937859:937860
@@ -93,11 +93,14 @@
 		QChildEvent *e = static_cast<QChildEvent *>(event);
 		void * childObj = (*GetInstance)(e->child(), true);
 		if (childObj != 0) {
+			smokeqyoto_object *o = (smokeqyoto_object*) (*GetSmokeObject)(childObj);
 			// Maybe add a check whether the childObj is still a QObject here
 			if (e->added()) {
 				(*AddGlobalRef)(childObj, e->child());
+				o->allocated = false;  // we don't need to care about deleting stuff anymore
 			} else {
 				(*RemoveGlobalRef)(childObj, e->child());
+				o->allocated = true;  // now we need to care about deletion again
 			}
 
 			(*FreeGCHandle)(childObj);
--- trunk/KDE/kdebindings/kalyptus/kalyptusCxxToKimono.pm #937859:937860
@@ -2683,7 +2683,7 @@
 					$staticMethodCode .= $csharpReturnType;
 	    			$staticMethodCode .= " $name($csharpparams) \{\n";
     				$staticMethodCode .= "            int result = (int) staticInterceptor.Invoke(\"exec\", \"exec()\", typeof(int));\n";
-    				$staticMethodCode .= "            Qyoto.SetApplicationTerminated();\n";
+    				$staticMethodCode .= "            Qyoto.Cleanup();\n";
     				$staticMethodCode .= "            return result;\n";
 		    		$staticMethodCode .= "        }\n";
 				} elsif ($isStatic or $classNode->{NodeType} eq 'namespace') {



More information about the Kde-bindings mailing list