Queue freeing of signals on the main-thread instead of on the Finalizer thread.

This commit is contained in:
Mads Kruse Johnsen 2020-11-19 16:41:06 +01:00
parent 470ce6cff7
commit 06b88bdbc5

View file

@ -33,7 +33,7 @@ namespace GLib {
IntPtr handle; IntPtr handle;
ToggleRef tref; ToggleRef tref;
bool disposed = false; bool disposed;
static uint idx = 1; static uint idx = 1;
static Dictionary<IntPtr, ToggleRef> Objects = new Dictionary<IntPtr, ToggleRef>(); static Dictionary<IntPtr, ToggleRef> Objects = new Dictionary<IntPtr, ToggleRef>();
static Dictionary<IntPtr, Dictionary<IntPtr, GLib.Value>> PropertiesToSet = new Dictionary<IntPtr, Dictionary<IntPtr, GLib.Value>>(); static Dictionary<IntPtr, Dictionary<IntPtr, GLib.Value>> PropertiesToSet = new Dictionary<IntPtr, Dictionary<IntPtr, GLib.Value>>();
@ -41,7 +41,7 @@ namespace GLib {
~Object () ~Object ()
{ {
if (WarnOnFinalize) if (WarnOnFinalize)
Console.Error.WriteLine ("Unexpected finalization of " + GetType() + " instance. Consider calling Dispose."); Console.Error.WriteLine ("Unexpected finalization of " + GetType() + " instance. Consider calling Dispose. (" + handle.ToInt64 () + ")");
Dispose (false); Dispose (false);
} }
@ -51,9 +51,10 @@ namespace GLib {
if (disposed) if (disposed)
return; return;
GC.SuppressFinalize (this);
Dispose (true); Dispose (true);
disposed = true; disposed = true;
GC.SuppressFinalize (this);
} }
protected virtual void Dispose (bool disposing) protected virtual void Dispose (bool disposing)
@ -70,19 +71,25 @@ namespace GLib {
return; return;
if (disposing) if (disposing)
{
tref.Dispose (); tref.Dispose ();
else
tref.QueueUnref ();
// Free all internal signals, else the garbage collector is not
// able to free the object.
if (signals != null) if (signals != null)
{ {
foreach (var sig in signals.Keys) foreach (var sig in signals.Keys)
signals[sig].Free (); signals[sig].Free ();
} }
}
else
{
if (signals != null)
QueueSignalFree ();
tref.QueueUnref ();
}
signals = null; signals = null;
disposed = true;
} }
public static bool WarnOnFinalize { get; set; } public static bool WarnOnFinalize { get; set; }
@ -807,6 +814,9 @@ namespace GLib {
GLib.Marshaller.Free (native_name); GLib.Marshaller.Free (native_name);
} }
public static List<Signal> PendingSignalFrees = new List<Signal> ();
static bool idle_queued;
Dictionary<string, Signal> signals; Dictionary<string, Signal> signals;
Dictionary<string, Signal> Signals { Dictionary<string, Signal> Signals {
get { get {
@ -853,6 +863,34 @@ namespace GLib {
sig.RemoveDelegate (handler); sig.RemoveDelegate (handler);
} }
public void QueueSignalFree ()
{
lock (PendingSignalFrees) {
PendingSignalFrees.AddRange (signals.Values);
if (!idle_queued){
Timeout.Add (50, new TimeoutHandler (PerformQueuedSignalFrees));
idle_queued = true;
}
}
}
static bool PerformQueuedSignalFrees ()
{
Signal[] qsignals;
lock (PendingSignalFrees){
qsignals = new Signal[PendingSignalFrees.Count];
PendingSignalFrees.CopyTo (qsignals, 0);
PendingSignalFrees.Clear ();
idle_queued = false;
}
foreach (Signal s in qsignals)
s.Free ();
return false;
}
protected static void OverrideVirtualMethod (GType gtype, string name, Delegate cb) protected static void OverrideVirtualMethod (GType gtype, string name, Delegate cb)
{ {
Signal.OverrideDefaultHandler (gtype, name, cb); Signal.OverrideDefaultHandler (gtype, name, cb);