From 06b88bdbc5ceb7abe4d9185a30cc474bbcd3ec74 Mon Sep 17 00:00:00 2001 From: Mads Kruse Johnsen Date: Thu, 19 Nov 2020 16:41:06 +0100 Subject: [PATCH] Queue freeing of signals on the main-thread instead of on the Finalizer thread. --- Source/Libs/GLibSharp/Object.cs | 62 ++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/Source/Libs/GLibSharp/Object.cs b/Source/Libs/GLibSharp/Object.cs index 3ab7f12f1..833b8e513 100644 --- a/Source/Libs/GLibSharp/Object.cs +++ b/Source/Libs/GLibSharp/Object.cs @@ -33,7 +33,7 @@ namespace GLib { IntPtr handle; ToggleRef tref; - bool disposed = false; + bool disposed; static uint idx = 1; static Dictionary Objects = new Dictionary(); static Dictionary> PropertiesToSet = new Dictionary>(); @@ -41,7 +41,7 @@ namespace GLib { ~Object () { 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); } @@ -51,9 +51,10 @@ namespace GLib { if (disposed) return; + GC.SuppressFinalize (this); + Dispose (true); disposed = true; - GC.SuppressFinalize (this); } protected virtual void Dispose (bool disposing) @@ -70,19 +71,25 @@ namespace GLib { return; if (disposing) - tref.Dispose (); - else - tref.QueueUnref (); - - // Free all internal signals, else the garbage collector is not - // able to free the object. - if (signals != null) { - foreach (var sig in signals.Keys) - signals[sig].Free (); + tref.Dispose (); + + if (signals != null) + { + foreach (var sig in signals.Keys) + signals[sig].Free (); + } + } + else + { + if (signals != null) + QueueSignalFree (); + + tref.QueueUnref (); } signals = null; + disposed = true; } public static bool WarnOnFinalize { get; set; } @@ -807,6 +814,9 @@ namespace GLib { GLib.Marshaller.Free (native_name); } + public static List PendingSignalFrees = new List (); + static bool idle_queued; + Dictionary signals; Dictionary Signals { get { @@ -853,6 +863,34 @@ namespace GLib { 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) { Signal.OverrideDefaultHandler (gtype, name, cb);