From 41d6f0bf284977e39519eb735ac5ca2e2bbf2bec Mon Sep 17 00:00:00 2001 From: Mads Kruse Johnsen Date: Thu, 19 Nov 2020 16:48:29 +0100 Subject: [PATCH] Queue freeing of GCHandles instead of freeing them immidiately --- Source/Libs/GLibSharp/ToggleRef.cs | 40 ++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/Source/Libs/GLibSharp/ToggleRef.cs b/Source/Libs/GLibSharp/ToggleRef.cs index 20517ac99..432257f69 100644 --- a/Source/Libs/GLibSharp/ToggleRef.cs +++ b/Source/Libs/GLibSharp/ToggleRef.cs @@ -71,8 +71,12 @@ namespace GLib { g_object_unref (handle); else g_object_remove_toggle_ref (handle, ToggleNotifyCallback, (IntPtr) gch); + reference = null; - gch.Free (); + + QueueGCHandleFree (); + + handle = IntPtr.Zero; } internal void Harden () @@ -97,7 +101,8 @@ namespace GLib { reference = new WeakReference (reference); else if (!is_last_ref && reference is WeakReference) { WeakReference weak = reference as WeakReference; - reference = weak.Target; + if (weak.IsAlive) + reference = weak.Target; } } @@ -124,6 +129,37 @@ namespace GLib { } } + static List PendingGCHandleFrees = new List (); + static bool gc_idle_queued; + + public void QueueGCHandleFree () + { + lock (PendingGCHandleFrees) { + PendingGCHandleFrees.Add (gch); + if (!gc_idle_queued){ + Timeout.Add (50, new TimeoutHandler (PerformGCHandleFrees)); + gc_idle_queued = true; + } + } + } + + static bool PerformGCHandleFrees () + { + GCHandle[] handles; + + lock (PendingGCHandleFrees){ + handles = new GCHandle [PendingGCHandleFrees.Count]; + PendingGCHandleFrees.CopyTo (handles, 0); + PendingGCHandleFrees.Clear (); + gc_idle_queued = false; + } + + foreach (GCHandle r in handles) + r.Free (); + + return false; + } + static List PendingDestroys = new List (); static bool idle_queued;