[Kde-bindings] playground/bindings/kimono

Richard Dale Richard_Dale at tipitina.demon.co.uk
Tue Mar 6 20:15:00 UTC 2007


SVN commit 640093 by rdale:

* A GCHandle was being used to hold the 'internalPointer' value in a 
  QModelIndex. A new one was being allocated everytime a new index
  was created by QAbstractItemModel.CreateIndex(), which meant that
  different GCHandles could hold the same underlying 'Target' instance.
  However, this meant that the equality operator for QModelIndex no longer
  worked correctly. So GCHandles for holding the InternalPointer() 
  references are kept in a Dictionary with the object instance to be 
  wrapped as the key. A reference count against the handle is used to 
  ensure that the GCHandle is freed once there are no references to it 
  via InternalPointer().

CCMAIL: kde-bindings at kde.org



 M  +11 -5     ChangeLog  
 M  +34 -15    core/QAbstractItemModelExtras.cs  
 M  +0 -3      core/QModelIndex.cs  
 M  +5 -0      core/QModelIndexExtras.cs  


--- trunk/playground/bindings/kimono/ChangeLog #640092:640093
@@ -1,9 +1,15 @@
-2007-03-06  Arno Rehn  <arno at arnorehn.de>
+2007-03-06  Richard Dale  <rdale at foton.es>
 
-	* GCHandles for QModelIndex'es are now stored in a Dictionary.
-	  QAbstractItemModel.CreateIndex() looks up a GCHandle in the Dictionary
-	  and if it exists it is passed to the C++ function. Child items of a tree model
-	  can now be selected.
+	* A GCHandle was being used to hold the 'internalPointer' value in a 
+	  QModelIndex. A new one was being allocated everytime a new index
+	  was created by QAbstractItemModel.CreateIndex(), which meant that
+	  different GCHandles could hold the same underlying 'Target' instance.
+	  However, this meant that the equality operator for QModelIndex no longer
+	  worked correctly. So GCHandles for holding the InternalPointer() 
+	  references are kept in a Dictionary with the object instance to be 
+	  wrapped as the key. A reference count against the handle is used to 
+	  ensure that the GCHandle is freed once there are no references to it 
+	  via InternalPointer().
 
 2007-03-05  Richard Dale  <rdale at foton.es>
 
--- trunk/playground/bindings/kimono/core/QAbstractItemModelExtras.cs #640092:640093
@@ -8,35 +8,54 @@
 		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
 		public static extern IntPtr AbstractItemModelCreateIndex(IntPtr obj, int row, int column, IntPtr ptr);
 		
-		private static Dictionary<WeakReference, GCHandle> handleMap = new Dictionary<WeakReference, GCHandle>();
+		private struct HandleRef {
+			public int refCount;
+			public GCHandle handle;
+		}
+
+		private static Dictionary<object, HandleRef> handleMap = new Dictionary<object, HandleRef>();
 		
 		protected QModelIndex CreateIndex(int row, int column, object ptr) {
 			IntPtr ret = AbstractItemModelCreateIndex((IntPtr) GCHandle.Alloc(this),
 									row, column, (IntPtr) GetIndexHandle(ptr));
-			return (QModelIndex) ((GCHandle) ret).Target;
+			QModelIndex result = (QModelIndex) ((GCHandle) ret).Target;
+			((GCHandle) ret).Free();
+			return result;
 		}
 		
 		protected QModelIndex CreateIndex(int row, int column) {
 			IntPtr ret = AbstractItemModelCreateIndex((IntPtr) GCHandle.Alloc(this),
 									row, column, IntPtr.Zero);
-			return (QModelIndex) ((GCHandle) ret).Target;
+			QModelIndex result = (QModelIndex) ((GCHandle) ret).Target;
+			((GCHandle) ret).Free();
+			return result;
 		}
 		
 		private GCHandle GetIndexHandle(object o) {
-			foreach (WeakReference weakRef in handleMap.Keys) {
-				if (weakRef.Target == o) {
-					// found
-					return handleMap[weakRef];
+			HandleRef reference;
+			if (!handleMap.TryGetValue(o, out reference)) {
+				reference = new HandleRef();
+				reference.refCount = 0;
+				reference.handle = GCHandle.Alloc(o);
+				handleMap.Add(o, reference);
+			}
+
+			reference.refCount += 1;
+			return reference.handle;
+		}
+		
+		static public void DerefIndexHandle(object o) {
+			HandleRef reference;
+			if (handleMap.TryGetValue(o, out reference)) {
+				reference.refCount -= 1;
+
+				if (reference.refCount == 0) {
+					reference.handle.Free();
+					handleMap.Remove(o);
 				}
-				
-				if (!weakRef.IsAlive) {
-					handleMap.Remove(weakRef);
-				}
 			}
-			
-			GCHandle handle = GCHandle.Alloc(o);
-			handleMap.Add(new WeakReference(o), handle);
-			return handle;
+
+			return ;
 		}
 	}
 }
--- trunk/playground/bindings/kimono/core/QModelIndex.cs #640092:640093
@@ -111,9 +111,6 @@
 			return !StaticQModelIndex().op_lt(lhs,other)
 						&& !StaticQModelIndex().op_equals(lhs,other);
 		}
-		~QModelIndex() {
-			DisposeQModelIndex();
-		}
 		public void Dispose() {
 			DisposeQModelIndex();
 		}
--- trunk/playground/bindings/kimono/core/QModelIndexExtras.cs #640092:640093
@@ -11,5 +11,10 @@
 			IntPtr ptr = ModelIndexInternalPointer((IntPtr) GCHandle.Alloc(this));
 			return ((GCHandle) ptr).Target;
 		}
+
+		~QModelIndex() {
+			QAbstractItemModel.DerefIndexHandle(InternalPointer());
+			DisposeQModelIndex();
+		}
 	}
 }



More information about the Kde-bindings mailing list