DynamicSignal: Add Dispose to SignalInfo

SignalInfo implements IDisposable to free GCHandle.

https://bugzilla.gnome.org/show_bug.cgi?id=793982
This commit is contained in:
Justin Kim 2018-03-01 12:36:23 +09:00 committed by Thibault Saunier
parent 2d00f898fb
commit b65093ab72

View file

@ -69,12 +69,13 @@ namespace Gst
} }
} }
class SignalInfo class SignalInfo : IDisposable
{ {
uint handlerId; uint handlerId;
IntPtr closure; IntPtr closure;
Delegate registeredHandler; Delegate registeredHandler;
Type argsType; Type argsType;
GCHandle gch;
public IntPtr Closure { public IntPtr Closure {
get { get {
@ -112,11 +113,12 @@ namespace Gst
} }
} }
public SignalInfo (uint handlerId, IntPtr closure, Delegate registeredHandler) public SignalInfo (uint handlerId, IntPtr closure, Delegate registeredHandler, GCHandle gch)
{ {
this.handlerId = handlerId; this.handlerId = handlerId;
this.closure = closure; this.closure = closure;
this.registeredHandler = registeredHandler; this.registeredHandler = registeredHandler;
this.gch = gch;
if (!IsValidDelegate (registeredHandler)) if (!IsValidDelegate (registeredHandler))
throw new Exception ("Invalid delegate"); throw new Exception ("Invalid delegate");
@ -164,6 +166,13 @@ namespace Gst
return true; return true;
} }
public void Dispose ()
{
registeredHandler = null;
gch.Free ();
GC.SuppressFinalize (this);
}
public static bool IsValidDelegate (Delegate d) public static bool IsValidDelegate (Delegate d)
{ {
MethodInfo mi = d.Method; MethodInfo mi = d.Method;
@ -227,9 +236,10 @@ namespace Gst
// Let's allocate 64bytes for the GClosure, it should be more than necessary. // Let's allocate 64bytes for the GClosure, it should be more than necessary.
IntPtr closure = g_closure_new_simple (64, IntPtr.Zero); IntPtr closure = g_closure_new_simple (64, IntPtr.Zero);
g_closure_set_meta_marshal (closure, (IntPtr)GCHandle.Alloc (k), marshalHandler); GCHandle gch = GCHandle.Alloc (k);
g_closure_set_meta_marshal (closure, (IntPtr)gch, marshalHandler);
uint signalId = g_signal_connect_closure (o.Handle, name, closure, after); uint signalId = g_signal_connect_closure (o.Handle, name, closure, after);
SignalHandlers.Add (k, new SignalInfo (signalId, closure, handler)); SignalHandlers.Add (k, new SignalInfo (signalId, closure, handler, gch));
} }
} }
@ -242,6 +252,7 @@ namespace Gst
if (newHandler == null || handler == null) { if (newHandler == null || handler == null) {
g_signal_handler_disconnect (o.Handle, si.HandlerId); g_signal_handler_disconnect (o.Handle, si.HandlerId);
SignalHandlers.Remove (k); SignalHandlers.Remove (k);
si.Dispose ();
} else { } else {
si.RegisteredHandler = newHandler; si.RegisteredHandler = newHandler;
} }