2008-01-22 Mike Kestner <mkestner@novell.com>

* glib/Object.cs: expose an internal ToggleRef prop.
	* glib/Signal.cs: use ToggleRef for lookups instead of Object. Add
	a Free method and release connections and gchandles.
	* glib/ToggleRef.cs: add signal hash and release signals on free.

svn path=/trunk/gtk-sharp/; revision=93548
This commit is contained in:
Mike Kestner 2008-01-22 16:54:44 +00:00
parent 5ccb3ccd2f
commit 776aeccdbb
4 changed files with 64 additions and 23 deletions

View File

@ -1,3 +1,10 @@
2008-01-22 Mike Kestner <mkestner@novell.com>
* glib/Object.cs: expose an internal ToggleRef prop.
* glib/Signal.cs: use ToggleRef for lookups instead of Object. Add
a Free method and release connections and gchandles.
* glib/ToggleRef.cs: add signal hash and release signals on free.
2008-01-17 Mike Kestner <mkestner@novell.com> 2008-01-17 Mike Kestner <mkestner@novell.com>
* glib/Object.cs: remove ref from Objects hash prior to releasing it. * glib/Object.cs: remove ref from Objects hash prior to releasing it.

View File

@ -32,6 +32,7 @@ namespace GLib {
public class Object : IWrapper, IDisposable { public class Object : IWrapper, IDisposable {
IntPtr handle; IntPtr handle;
ToggleRef tref;
bool disposed = false; bool disposed = false;
Hashtable data; Hashtable data;
static Hashtable Objects = new Hashtable(); static Hashtable Objects = new Hashtable();
@ -295,14 +296,17 @@ namespace GLib {
return; return;
if (handle != IntPtr.Zero) { if (handle != IntPtr.Zero) {
ToggleRef tref = Objects [handle] as ToggleRef;
Objects.Remove (handle); Objects.Remove (handle);
if (tref != null) if (tref != null) {
tref.Free (); tref.Free ();
tref = null;
}
} }
handle = value; handle = value;
if (value != IntPtr.Zero) if (value != IntPtr.Zero) {
Objects [value] = new ToggleRef (this); tref = new ToggleRef (this);
Objects [value] = tref;
}
} }
} }
@ -327,23 +331,19 @@ namespace GLib {
} }
} }
internal ToggleRef ToggleRef {
get {
return tref;
}
}
public IntPtr Handle { public IntPtr Handle {
get { get {
return handle; return handle;
} }
} }
Hashtable signals;
internal Hashtable Signals {
get {
if (signals == null)
signals = new Hashtable ();
return signals;
}
}
Hashtable before_signals; Hashtable before_signals;
[Obsolete ("Replaced by GLib.Signal marshaling mechanism.")] [Obsolete ("Replaced by GLib.Signal marshaling mechanism.")]
protected Hashtable BeforeSignals { protected Hashtable BeforeSignals {
get { get {

View File

@ -22,6 +22,7 @@
namespace GLib { namespace GLib {
using System; using System;
using System.Collections;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
[Flags] [Flags]
@ -51,19 +52,33 @@ namespace GLib {
public class Signal { public class Signal {
GCHandle gc_handle; GCHandle gc_handle;
Object obj; ToggleRef tref;
string name; string name;
uint before_id = UInt32.MaxValue; uint before_id = UInt32.MaxValue;
uint after_id = UInt32.MaxValue; uint after_id = UInt32.MaxValue;
Delegate marshaler; Delegate marshaler;
~Signal ()
{
gc_handle.Free ();
}
private Signal (GLib.Object obj, string signal_name, Delegate marshaler) private Signal (GLib.Object obj, string signal_name, Delegate marshaler)
{ {
this.obj = obj; tref = obj.ToggleRef;
name = signal_name; name = signal_name;
this.marshaler = marshaler; this.marshaler = marshaler;
gc_handle = GCHandle.Alloc (this, GCHandleType.Weak); gc_handle = GCHandle.Alloc (this, GCHandleType.Weak);
obj.Signals [name] = this; tref.Signals [name] = this;
}
internal void Free ()
{
DisconnectHandler (before_id);
DisconnectHandler (after_id);
before_handler = after_handler = marshaler = null;
gc_handle.Free ();
GC.SuppressFinalize (this);
} }
public static Signal Lookup (GLib.Object obj, string name) public static Signal Lookup (GLib.Object obj, string name)
@ -73,7 +88,7 @@ namespace GLib {
public static Signal Lookup (GLib.Object obj, string name, Delegate marshaler) public static Signal Lookup (GLib.Object obj, string name, Delegate marshaler)
{ {
Signal result = obj.Signals [name] as Signal; Signal result = obj.ToggleRef.Signals [name] as Signal;
if (result == null) if (result == null)
result = new Signal (obj, name, marshaler); result = new Signal (obj, name, marshaler);
return result as Signal; return result as Signal;
@ -84,7 +99,7 @@ namespace GLib {
public Delegate Handler { public Delegate Handler {
get { get {
InvocationHint hint = (InvocationHint) Marshal.PtrToStructure (g_signal_get_invocation_hint (obj.Handle), typeof (InvocationHint)); InvocationHint hint = (InvocationHint) Marshal.PtrToStructure (g_signal_get_invocation_hint (tref.Handle), typeof (InvocationHint));
if (hint.run_type == SignalFlags.RunFirst) if (hint.run_type == SignalFlags.RunFirst)
return before_handler; return before_handler;
else else
@ -95,7 +110,7 @@ namespace GLib {
uint Connect (int flags) uint Connect (int flags)
{ {
IntPtr native_name = GLib.Marshaller.StringToPtrGStrdup (name); IntPtr native_name = GLib.Marshaller.StringToPtrGStrdup (name);
uint id = g_signal_connect_data (obj.Handle, native_name, marshaler, (IntPtr) gc_handle, IntPtr.Zero, flags); uint id = g_signal_connect_data (tref.Handle, native_name, marshaler, (IntPtr) gc_handle, IntPtr.Zero, flags);
GLib.Marshaller.Free (native_name); GLib.Marshaller.Free (native_name);
return id; return id;
} }
@ -134,13 +149,13 @@ namespace GLib {
} }
if (after_id == UInt32.MaxValue && before_id == UInt32.MaxValue) if (after_id == UInt32.MaxValue && before_id == UInt32.MaxValue)
obj.Signals.Remove (name); tref.Signals.Remove (name);
} }
void DisconnectHandler (uint handler_id) void DisconnectHandler (uint handler_id)
{ {
if (handler_id != UInt32.MaxValue && g_signal_handler_is_connected (obj.Handle, handler_id)) if (handler_id != UInt32.MaxValue && g_signal_handler_is_connected (tref.Handle, handler_id))
g_signal_handler_disconnect (obj.Handle, handler_id); g_signal_handler_disconnect (tref.Handle, handler_id);
} }
[CDeclCallback] [CDeclCallback]

View File

@ -22,6 +22,7 @@
namespace GLib { namespace GLib {
using System; using System;
using System.Collections;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
internal class ToggleRef { internal class ToggleRef {
@ -29,6 +30,7 @@ namespace GLib {
IntPtr handle; IntPtr handle;
object reference; object reference;
GCHandle gch; GCHandle gch;
Hashtable signals;
public ToggleRef (GLib.Object target) public ToggleRef (GLib.Object target)
{ {
@ -50,6 +52,20 @@ namespace GLib {
} }
} }
public IntPtr Handle {
get {
return handle;
}
}
public Hashtable Signals {
get {
if (signals == null)
signals = new Hashtable ();
return signals;
}
}
public GLib.Object Target { public GLib.Object Target {
get { get {
if (reference is GLib.Object) if (reference is GLib.Object)
@ -62,6 +78,9 @@ namespace GLib {
public void Free () public void Free ()
{ {
foreach (Signal s in Signals.Values)
s.Free ();
Signals.Clear ();
g_object_remove_toggle_ref (handle, ToggleNotifyCallback, (IntPtr) gch); g_object_remove_toggle_ref (handle, ToggleNotifyCallback, (IntPtr) gch);
reference = null; reference = null;
gch.Free (); gch.Free ();