diff --git a/src/Godot.Bindings/Core/GodotObject.cs b/src/Godot.Bindings/Core/GodotObject.cs index d4393f1e..05c42505 100644 --- a/src/Godot.Bindings/Core/GodotObject.cs +++ b/src/Godot.Bindings/Core/GodotObject.cs @@ -13,7 +13,7 @@ partial class GodotObject : IDisposable internal nint NativePtr; private readonly GCHandle _gcHandle; - private readonly WeakReference? _weakReferenceToSelf; + private readonly WeakReference? _weakReferenceToSelf; private bool _disposed; @@ -206,10 +206,7 @@ protected unsafe virtual void Dispose(bool disposing) NativePtr = 0; } - if (_weakReferenceToSelf is not null) - { - DisposablesTracker.UnregisterGodotObject(this, _weakReferenceToSelf); - } + DisposablesTracker.UnregisterGodotObject(this, _weakReferenceToSelf); } /// diff --git a/src/Godot.Bindings/NativeInterop/DisposablesTracker.cs b/src/Godot.Bindings/NativeInterop/DisposablesTracker.cs index 3cf4e0f3..2974f54f 100644 --- a/src/Godot.Bindings/NativeInterop/DisposablesTracker.cs +++ b/src/Godot.Bindings/NativeInterop/DisposablesTracker.cs @@ -6,9 +6,12 @@ namespace Godot.NativeInterop; internal static class DisposablesTracker { - private static readonly ConcurrentDictionary, byte> _godotObjectInstances = + private static readonly ConcurrentDictionary _godotObjectInstances = new(); + private static readonly ConcurrentDictionary, byte> _refCountedInstances = + new(); + private static readonly ConcurrentDictionary, byte> _otherInstances = new(); @@ -25,9 +28,14 @@ internal static void DisposeAll() // like StringName, NodePath, GodotArray/GodotDictionary, etc. // The GodotObject Dispose() method may need any of the later instances. - foreach (WeakReference item in _godotObjectInstances.Keys) + foreach (GodotObject self in _godotObjectInstances.Keys) + { + self.Dispose(); + } + + foreach (WeakReference item in _refCountedInstances.Keys) { - if (item.TryGetTarget(out GodotObject? self)) + if (item.TryGetTarget(out RefCounted? self)) { self.Dispose(); } @@ -47,11 +55,16 @@ internal static void DisposeAll() } } - public static WeakReference RegisterGodotObject(GodotObject godotObject) + public static WeakReference? RegisterGodotObject(GodotObject godotObject) { - var weakReferenceToSelf = new WeakReference(godotObject); - _godotObjectInstances.TryAdd(weakReferenceToSelf, 0); - return weakReferenceToSelf; + if (godotObject is RefCounted rc) + { + var weakReferenceToSelf = new WeakReference(rc); + _refCountedInstances.TryAdd(weakReferenceToSelf, 0); + return weakReferenceToSelf; + } + _godotObjectInstances.TryAdd(godotObject, 0); + return null; } public static WeakReference RegisterDisposable(IDisposable disposable) @@ -63,9 +76,9 @@ public static WeakReference RegisterDisposable(IDisposable disposab return weakReferenceToSelf; } - public static void UnregisterGodotObject(GodotObject godotObject, WeakReference weakReferenceToSelf) + public static void UnregisterGodotObject(GodotObject godotObject, WeakReference? weakReferenceToSelf) { - if (!_godotObjectInstances.TryRemove(weakReferenceToSelf, out _)) + if (godotObject is RefCounted rc ? !_refCountedInstances.TryRemove(weakReferenceToSelf!, out _) : !_godotObjectInstances.TryRemove(godotObject, out _)) { throw new ArgumentException("Godot Object not registered.", nameof(weakReferenceToSelf)); }