From 4a8f91845f0cf4f7158e3fc2f9afde482aad3657 Mon Sep 17 00:00:00 2001 From: DE YU <71481700+Delsin-Yu@users.noreply.github.com> Date: Sat, 31 Aug 2024 21:34:12 +0800 Subject: [PATCH] Implment managed object reference count --- .../glue/GodotSharp/GodotSharp/Core/Array.cs | 33 ++++++++++++++++++- .../GodotSharp/GodotSharp/Core/Dictionary.cs | 32 +++++++++++++++++- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs index fb1d32c0cb3d..efe164149a37 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs @@ -31,6 +31,8 @@ public sealed class Array : private WeakReference? _weakReferenceToSelf; + internal int TypedWrapperReferenceCount; + /// /// Constructs a new empty . /// @@ -1052,7 +1054,8 @@ public sealed class Array<[MustBeVariant] T> : IReadOnlyList, ICollection, IEnumerable, - IGenericGodotArray + IGenericGodotArray, + IDisposable { private static godot_variant ToVariantFunc(in Array godotArray) => VariantUtils.CreateFromArray(godotArray); @@ -1067,6 +1070,7 @@ static unsafe Array() } private readonly Array _underlyingArray; + private bool _disposed; Array IGenericGodotArray.UnderlyingArray => _underlyingArray; @@ -1083,6 +1087,7 @@ internal ref godot_array.movable NativeValue public Array() { _underlyingArray = new Array(); + _underlyingArray.TypedWrapperReferenceCount++; } /// @@ -1099,6 +1104,7 @@ public Array(IEnumerable collection) throw new ArgumentNullException(nameof(collection)); _underlyingArray = new Array(); + _underlyingArray.TypedWrapperReferenceCount++; foreach (T element in collection) Add(element); @@ -1118,6 +1124,7 @@ public Array(T[] array) throw new ArgumentNullException(nameof(array)); _underlyingArray = new Array(); + _underlyingArray.TypedWrapperReferenceCount++; foreach (T element in array) Add(element); @@ -1137,6 +1144,7 @@ public Array(Array array) throw new ArgumentNullException(nameof(array)); _underlyingArray = array; + _underlyingArray.TypedWrapperReferenceCount++; } // Explicit name to make it very clear @@ -1154,6 +1162,29 @@ internal static Array CreateTakingOwnershipOfDisposableValue(godot_array nati return from?._underlyingArray; } + ~Array() + { + Dispose(false); + } + + /// + /// Disposes of this . + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + public void Dispose(bool disposing) + { + if(_disposed) return; + _disposed = true; + _underlyingArray.TypedWrapperReferenceCount--; + if(_underlyingArray.TypedWrapperReferenceCount > 0) return; + _underlyingArray.Dispose(disposing); + } + /// /// Duplicates this . /// diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs index 864815866ae5..29084329006c 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs @@ -26,6 +26,8 @@ public sealed class Dictionary : private WeakReference? _weakReferenceToSelf; + internal int TypedWrapperReferenceCount; + /// /// Constructs a new empty . /// @@ -488,7 +490,8 @@ internal interface IGenericGodotDictionary public class Dictionary<[MustBeVariant] TKey, [MustBeVariant] TValue> : IDictionary, IReadOnlyDictionary, - IGenericGodotDictionary + IGenericGodotDictionary, + IDisposable { private static godot_variant ToVariantFunc(in Dictionary godotDictionary) => VariantUtils.CreateFromDictionary(godotDictionary); @@ -503,6 +506,7 @@ static unsafe Dictionary() } private readonly Dictionary _underlyingDict; + private bool _disposed; Dictionary IGenericGodotDictionary.UnderlyingDictionary => _underlyingDict; @@ -519,6 +523,7 @@ internal ref godot_dictionary.movable NativeValue public Dictionary() { _underlyingDict = new Dictionary(); + _underlyingDict.TypedWrapperReferenceCount++; } /// @@ -535,6 +540,7 @@ public Dictionary(IDictionary dictionary) throw new ArgumentNullException(nameof(dictionary)); _underlyingDict = new Dictionary(); + _underlyingDict.TypedWrapperReferenceCount++; foreach (KeyValuePair entry in dictionary) Add(entry.Key, entry.Value); @@ -554,6 +560,7 @@ public Dictionary(Dictionary dictionary) throw new ArgumentNullException(nameof(dictionary)); _underlyingDict = dictionary; + _underlyingDict.TypedWrapperReferenceCount++; } // Explicit name to make it very clear @@ -572,6 +579,29 @@ internal static Dictionary CreateTakingOwnershipOfDisposableValue( return from?._underlyingDict; } + ~Dictionary() + { + Dispose(false); + } + + /// + /// Disposes of this . + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + public void Dispose(bool disposing) + { + if(_disposed) return; + _disposed = true; + _underlyingDict.TypedWrapperReferenceCount--; + if(_underlyingDict.TypedWrapperReferenceCount > 0) return; + _underlyingDict.Dispose(disposing); + } + /// /// Returns a copy of the . /// If is , a deep copy is performed: