From 70018d857d3d70342bb4e01cecf69d6b3b61fdf4 Mon Sep 17 00:00:00 2001 From: Mike Kestner Date: Fri, 16 Nov 2007 18:35:38 +0000 Subject: [PATCH] 2007-11-16 Mike Kestner * glib/Object.cs: use toggle refs for all objects. de-obsolete Data hash. Add internal Signals hash. * glib/Signal.cs: switch to weak gchandles. * glib/WeakObject.cs: kill. svn path=/trunk/gtk-sharp/; revision=89776 --- ChangeLog | 7 +++ glib/Makefile.am | 3 +- glib/Object.cs | 113 ++++++++++++++++++++++++--------------------- glib/Signal.cs | 54 ++++++---------------- glib/WeakObject.cs | 94 ------------------------------------- 5 files changed, 81 insertions(+), 190 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9a9609c19..e68ffba2e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2007-11-16 Mike Kestner + + * glib/Object.cs: use toggle refs for all objects. + de-obsolete Data hash. Add internal Signals hash. + * glib/Signal.cs: switch to weak gchandles. + * glib/WeakObject.cs: kill. + 2007-11-16 Eskil Bylund * gtk/ListStore.custom: diff --git a/glib/Makefile.am b/glib/Makefile.am index c44dfd10d..b15780cc5 100644 --- a/glib/Makefile.am +++ b/glib/Makefile.am @@ -67,8 +67,7 @@ sources = \ TypeInitializerAttribute.cs \ UnwrappedObject.cs \ ValueArray.cs \ - Value.cs \ - WeakObject.cs + Value.cs build_sources = $(addprefix $(srcdir)/, $(sources)) AssemblyInfo.cs dist_sources = $(sources) diff --git a/glib/Object.cs b/glib/Object.cs index 32f71c4fa..25eebcf4b 100644 --- a/glib/Object.cs +++ b/glib/Object.cs @@ -31,7 +31,7 @@ namespace GLib { public class Object : IWrapper, IDisposable { - IntPtr _obj; + IntPtr handle; bool disposed = false; Hashtable data; static Hashtable Objects = new Hashtable(); @@ -40,13 +40,15 @@ namespace GLib { ~Object () { - lock (PendingDestroys){ - PendingDestroys.Add (this); - lock (typeof (Object)){ - if (!idle_queued){ - Timeout.Add (50, new TimeoutHandler (PerformQueuedUnrefs)); - idle_queued = true; - } + lock (PendingDestroys) { + lock (Objects) { + if (Objects[Handle] is ToggleRef) + PendingDestroys.Add (Objects [Handle]); + Objects.Remove (Handle); + } + if (!idle_queued){ + Timeout.Add (50, new TimeoutHandler (PerformQueuedUnrefs)); + idle_queued = true; } } } @@ -56,22 +58,18 @@ namespace GLib { static bool PerformQueuedUnrefs () { - Object [] objects; + object [] references; lock (PendingDestroys){ - objects = new Object [PendingDestroys.Count]; - PendingDestroys.CopyTo (objects, 0); + references = new object [PendingDestroys.Count]; + PendingDestroys.CopyTo (references, 0); PendingDestroys.Clear (); - } - lock (typeof (Object)) idle_queued = false; - - foreach (Object o in objects){ - if (o._obj == IntPtr.Zero) - continue; - - o.Dispose (); } + + foreach (ToggleRef r in references) + r.Free (); + return false; } @@ -82,17 +80,15 @@ namespace GLib { disposed = true; try { - ToggleRef toggle_ref = Objects [_obj] as ToggleRef; - if (toggle_ref == null) - g_object_unref (_obj); - else + ToggleRef toggle_ref = Objects [Handle] as ToggleRef; + if (toggle_ref != null) toggle_ref.Free (); } catch (Exception e) { Console.WriteLine ("Exception while disposing a " + this + " in Gtk#"); throw e; } - Objects.Remove (_obj); - _obj = IntPtr.Zero; + Objects.Remove (Handle); + handle = IntPtr.Zero; GC.SuppressFinalize (this); } @@ -105,34 +101,28 @@ namespace GLib { return null; Object obj = null; - object reference = Objects[o]; - if (reference is WeakReference) { - WeakReference weak_ref = reference as WeakReference; - if (weak_ref.IsAlive) - obj = weak_ref.Target as Object; - } else if (reference is ToggleRef) { - ToggleRef toggle_ref = reference as ToggleRef; - if (toggle_ref.IsAlive) + if (Objects.Contains (o)) { + ToggleRef toggle_ref = Objects [o] as ToggleRef; + if (toggle_ref != null && toggle_ref.IsAlive) obj = toggle_ref.Target; } - if (obj != null && obj._obj == o) { - lock (PendingDestroys) - PendingDestroys.Remove (obj); + if (obj != null && obj.Handle == o) { if (owned_ref) - g_object_unref (obj._obj); - obj.disposed = false; + g_object_unref (obj.Handle); return obj; } - obj = GLib.ObjectManager.CreateObject(o); - if (obj == null) - return null; - if (!owned_ref) g_object_ref (obj.Handle); - Objects [o] = new WeakReference (obj); + + obj = GLib.ObjectManager.CreateObject(o); + if (obj == null) { + g_object_unref (o); + return null; + } + return obj; } @@ -292,22 +282,27 @@ namespace GLib { for (int i = 0; i < names.Length; i++) native_names [i] = GLib.Marshaller.StringToPtrGStrdup (names [i]); Raw = gtksharp_object_newv (LookupGType ().Val, names.Length, native_names, vals); - Objects [_obj] = new ToggleRef (this); foreach (IntPtr p in native_names) GLib.Marshaller.Free (p); } protected virtual IntPtr Raw { get { - return _obj; + return handle; } set { - if (_obj != IntPtr.Zero) - Objects.Remove (_obj); - _obj = value; - if (value == IntPtr.Zero) + if (handle == value) return; - Objects [value] = new WeakReference (this); + + if (handle != IntPtr.Zero) { + ToggleRef tref = Objects [handle] as ToggleRef; + if (tref != null) + tref.Free (); + Objects.Remove (handle); + } + handle = value; + if (value != IntPtr.Zero) + Objects [value] = new ToggleRef (this); } } @@ -334,7 +329,16 @@ namespace GLib { public IntPtr Handle { get { - return _obj; + return handle; + } + } + + Hashtable signals; + internal Hashtable Signals { + get { + if (signals == null) + signals = new Hashtable (); + return signals; } } @@ -436,7 +440,6 @@ namespace GLib { return Handle.GetHashCode (); } - [Obsolete("Can cause instability due to garbage collection of GLib.Objects.")] public Hashtable Data { get { if (data == null) @@ -446,9 +449,13 @@ namespace GLib { } } + Hashtable persistent_data; protected Hashtable PersistentData { get { - return WeakObject.Lookup (Handle).Data; + if (persistent_data == null) + persistent_data = new Hashtable (); + + return persistent_data; } } diff --git a/glib/Signal.cs b/glib/Signal.cs index 8d6e785df..62d333dcb 100644 --- a/glib/Signal.cs +++ b/glib/Signal.cs @@ -45,7 +45,7 @@ namespace GLib { public class Signal { GCHandle gc_handle; - IntPtr handle; + Object obj; string name; uint before_id = UInt32.MaxValue; uint after_id = UInt32.MaxValue; @@ -53,14 +53,11 @@ namespace GLib { private Signal (GLib.Object obj, string signal_name, Delegate marshaler) { - handle = obj.Handle; + this.obj = obj; name = signal_name; this.marshaler = marshaler; - gc_handle = GCHandle.Alloc (this); - IntPtr native_key = GLib.Marshaller.StringToPtrGStrdup (name + "_signal_marshaler"); - if (handle != IntPtr.Zero) - g_object_set_data_full (handle, native_key, (IntPtr) gc_handle, DestroyHelper.NotifyHandler); - GLib.Marshaller.Free (native_key); + gc_handle = GCHandle.Alloc (this, GCHandleType.Weak); + obj.Signals [name] = this; } public static Signal Lookup (GLib.Object obj, string name) @@ -70,18 +67,10 @@ namespace GLib { public static Signal Lookup (GLib.Object obj, string name, Delegate marshaler) { - IntPtr native_key = GLib.Marshaller.StringToPtrGStrdup (name + "_signal_marshaler"); - IntPtr data; - if (obj.Handle == IntPtr.Zero) - data = IntPtr.Zero; - else - data = g_object_get_data (obj.Handle, native_key); - GLib.Marshaller.Free (native_key); - if (data == IntPtr.Zero) - return new Signal (obj, name, marshaler); - - GCHandle gch = (GCHandle) data; - return gch.Target as Signal; + Signal result = obj.Signals [name] as Signal; + if (result == null) + result = new Signal (obj, name, marshaler); + return result as Signal; } Delegate before_handler; @@ -89,7 +78,7 @@ namespace GLib { public Delegate Handler { get { - InvocationHint hint = (InvocationHint) Marshal.PtrToStructure (g_signal_get_invocation_hint (handle), typeof (InvocationHint)); + InvocationHint hint = (InvocationHint) Marshal.PtrToStructure (g_signal_get_invocation_hint (obj.Handle), typeof (InvocationHint)); if (hint.run_type == SignalFlags.RunFirst) return before_handler; else @@ -100,7 +89,7 @@ namespace GLib { uint Connect (int flags) { IntPtr native_name = GLib.Marshaller.StringToPtrGStrdup (name); - uint id = g_signal_connect_data (handle, native_name, marshaler, (IntPtr) gc_handle, IntPtr.Zero, flags); + uint id = g_signal_connect_data (obj.Handle, native_name, marshaler, (IntPtr) gc_handle, IntPtr.Zero, flags); GLib.Marshaller.Free (native_name); return id; } @@ -139,21 +128,13 @@ namespace GLib { } if (after_id == UInt32.MaxValue && before_id == UInt32.MaxValue) - DisconnectObject (); - } - - void DisconnectObject () - { - IntPtr native_key = GLib.Marshaller.StringToPtrGStrdup (name + "_signal_marshaler"); - if (handle != IntPtr.Zero) - g_object_set_data (handle, native_key, IntPtr.Zero); - GLib.Marshaller.Free (native_key); + obj.Signals.Remove (name); } void DisconnectHandler (uint handler_id) { - if (handler_id != UInt32.MaxValue && g_signal_handler_is_connected (handle, handler_id)) - g_signal_handler_disconnect (handle, handler_id); + if (handler_id != UInt32.MaxValue && g_signal_handler_is_connected (obj.Handle, handler_id)) + g_signal_handler_disconnect (obj.Handle, handler_id); } [CDeclCallback] @@ -186,15 +167,6 @@ namespace GLib { } } - [DllImport("libgobject-2.0-0.dll")] - static extern IntPtr g_object_get_data (IntPtr instance, IntPtr key); - - [DllImport("libgobject-2.0-0.dll")] - static extern void g_object_set_data (IntPtr instance, IntPtr key, IntPtr data); - - [DllImport("libgobject-2.0-0.dll")] - static extern void g_object_set_data_full (IntPtr instance, IntPtr key, IntPtr data, DestroyNotify notify); - [DllImport("libgobject-2.0-0.dll")] static extern uint g_signal_connect_data(IntPtr obj, IntPtr name, Delegate cb, IntPtr gc_handle, IntPtr dummy, int flags); diff --git a/glib/WeakObject.cs b/glib/WeakObject.cs index 7676d56a9..e69de29bb 100644 --- a/glib/WeakObject.cs +++ b/glib/WeakObject.cs @@ -1,94 +0,0 @@ -// WeakObject.cs - Object to hold managed references via native weakref. -// -// Authors: Mike Kestner -// -// Copyright (c) 2005 Novell, Inc. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of version 2 of the Lesser GNU General -// Public License as published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this program; if not, write to the -// Free Software Foundation, Inc., 59 Temple Place - Suite 330, -// Boston, MA 02111-1307, USA. - - -namespace GLib { - - using System; - using System.Collections; - using System.Runtime.InteropServices; - - internal class WeakObject { - - GCHandle gc_handle; - - static DestroyNotify notify = new DestroyNotify (OnNativeDestroy); - [CDeclCallback] - delegate void DestroyNotify (IntPtr data); - static void OnNativeDestroy (IntPtr data) - { - try { - GCHandle gch = (GCHandle) data; - WeakObject obj = gch.Target as WeakObject; - obj.Dispose (); - gch.Free (); - } catch (Exception e) { - ExceptionManager.RaiseUnhandledException (e, false); - } - } - - void Dispose () - { - signals = null; - data = null; - } - - WeakObject (IntPtr obj) - { - gc_handle = GCHandle.Alloc (this); - g_object_set_data_full (obj, "gtk_sharp_weak_object", (IntPtr) gc_handle, notify); - } - - Hashtable data; - public Hashtable Data { - get { - if (data == null) - data = new Hashtable (); - return data; - } - } - - Hashtable signals; - public Hashtable Signals { - get { - if (signals == null) - signals = new Hashtable (); - return signals; - } - } - - public static WeakObject Lookup (IntPtr obj) - { - IntPtr data = g_object_get_data (obj, "gtk_sharp_weak_object"); - if (data == IntPtr.Zero) - return new WeakObject (obj); - - GCHandle gch = (GCHandle) data; - return gch.Target as WeakObject; - } - - [DllImport("libgobject-2.0-0.dll")] - static extern IntPtr g_object_get_data (IntPtr instance, string key); - - [DllImport("libgobject-2.0-0.dll")] - static extern void g_object_set_data_full (IntPtr instance, string key, IntPtr data, DestroyNotify notify); - } -} -