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

View file

@ -22,6 +22,7 @@
namespace GLib {
using System;
using System.Collections;
using System.Runtime.InteropServices;
[Flags]
@ -51,19 +52,33 @@ namespace GLib {
public class Signal {
GCHandle gc_handle;
Object obj;
ToggleRef tref;
string name;
uint before_id = UInt32.MaxValue;
uint after_id = UInt32.MaxValue;
Delegate marshaler;
~Signal ()
{
gc_handle.Free ();
}
private Signal (GLib.Object obj, string signal_name, Delegate marshaler)
{
this.obj = obj;
tref = obj.ToggleRef;
name = signal_name;
this.marshaler = marshaler;
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)
@ -73,7 +88,7 @@ namespace GLib {
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)
result = new Signal (obj, name, marshaler);
return result as Signal;
@ -84,7 +99,7 @@ namespace GLib {
public Delegate Handler {
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)
return before_handler;
else
@ -95,7 +110,7 @@ namespace GLib {
uint Connect (int flags)
{
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);
return id;
}
@ -134,13 +149,13 @@ namespace GLib {
}
if (after_id == UInt32.MaxValue && before_id == UInt32.MaxValue)
obj.Signals.Remove (name);
tref.Signals.Remove (name);
}
void DisconnectHandler (uint handler_id)
{
if (handler_id != UInt32.MaxValue && g_signal_handler_is_connected (obj.Handle, handler_id))
g_signal_handler_disconnect (obj.Handle, handler_id);
if (handler_id != UInt32.MaxValue && g_signal_handler_is_connected (tref.Handle, handler_id))
g_signal_handler_disconnect (tref.Handle, handler_id);
}
[CDeclCallback]

View file

@ -22,6 +22,7 @@
namespace GLib {
using System;
using System.Collections;
using System.Runtime.InteropServices;
internal class ToggleRef {
@ -29,6 +30,7 @@ namespace GLib {
IntPtr handle;
object reference;
GCHandle gch;
Hashtable signals;
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 {
get {
if (reference is GLib.Object)
@ -62,6 +78,9 @@ namespace GLib {
public void Free ()
{
foreach (Signal s in Signals.Values)
s.Free ();
Signals.Clear ();
g_object_remove_toggle_ref (handle, ToggleNotifyCallback, (IntPtr) gch);
reference = null;
gch.Free ();