diff --git a/RGB.NET.Core/Devices/AbstractRGBDevice.cs b/RGB.NET.Core/Devices/AbstractRGBDevice.cs index 6ac90da..faaf147 100644 --- a/RGB.NET.Core/Devices/AbstractRGBDevice.cs +++ b/RGB.NET.Core/Devices/AbstractRGBDevice.cs @@ -85,6 +85,8 @@ public abstract class AbstractRGBDevice : Placeable, IRGBDevice : Placeable, IRGBDevice public virtual void Dispose() { - try { UpdateQueue.Dispose(); } catch { /* :( */ } + try + { + UpdateQueue.RemoveReferencingObject(this); + UpdateQueue.Dispose(); + } + catch { /* :( */ } try { LedMapping.Clear(); } catch { /* this really shouldn't happen */ } IdGenerator.ResetCounter(GetType().Assembly); diff --git a/RGB.NET.Core/Extensions/ReferenceCountingExtension.cs b/RGB.NET.Core/Extensions/ReferenceCountingExtension.cs new file mode 100644 index 0000000..58039eb --- /dev/null +++ b/RGB.NET.Core/Extensions/ReferenceCountingExtension.cs @@ -0,0 +1,6 @@ +namespace RGB.NET.Core; + +public static class ReferenceCountingExtension +{ + public static bool HasActiveReferences(this IReferenceCounting target) => target.ActiveReferenceCount > 0; +} \ No newline at end of file diff --git a/RGB.NET.Core/Misc/AbstractReferenceCounting.cs b/RGB.NET.Core/Misc/AbstractReferenceCounting.cs new file mode 100644 index 0000000..070138a --- /dev/null +++ b/RGB.NET.Core/Misc/AbstractReferenceCounting.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; + +namespace RGB.NET.Core; + +public abstract class AbstractReferenceCounting : IReferenceCounting +{ + #region Properties & Fields + + private readonly HashSet _referencingObjects = new(); + + /// + public int ActiveReferenceCount + { + get + { + lock (_referencingObjects) + return _referencingObjects.Count; + } + } + + #endregion + + #region Methods + + /// + public void AddReferencingObject(object obj) + { + lock (_referencingObjects) + if (!_referencingObjects.Contains(obj)) + _referencingObjects.Add(obj); + } + + /// + public void RemoveReferencingObject(object obj) + { + lock (_referencingObjects) + _referencingObjects.Remove(obj); + } + + #endregion +} \ No newline at end of file diff --git a/RGB.NET.Core/Misc/IReferenceCounting.cs b/RGB.NET.Core/Misc/IReferenceCounting.cs new file mode 100644 index 0000000..d8bcb28 --- /dev/null +++ b/RGB.NET.Core/Misc/IReferenceCounting.cs @@ -0,0 +1,21 @@ +namespace RGB.NET.Core; + +public interface IReferenceCounting +{ + /// + /// Gets the amount of currently registered referencing objects. + /// + public int ActiveReferenceCount { get; } + + /// + /// Adds the given object to the list of referencing objects. + /// + /// The object to add. + public void AddReferencingObject(object obj); + + /// + /// Removes the given object from the list of referencing objects. + /// + /// The object to remove. + public void RemoveReferencingObject(object obj); +} \ No newline at end of file diff --git a/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings b/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings index bf7655f..7f9a6e2 100644 --- a/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings +++ b/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings @@ -16,6 +16,7 @@ True True True + True True True True diff --git a/RGB.NET.Core/Update/Devices/IUpdateQueue.cs b/RGB.NET.Core/Update/Devices/IUpdateQueue.cs index 348c16e..bf4011c 100644 --- a/RGB.NET.Core/Update/Devices/IUpdateQueue.cs +++ b/RGB.NET.Core/Update/Devices/IUpdateQueue.cs @@ -8,7 +8,7 @@ namespace RGB.NET.Core; /// /// The identifier used to identify the data processed by this queue. /// The type of the data processed by this queue. -public interface IUpdateQueue : IDisposable +public interface IUpdateQueue : IReferenceCounting, IDisposable where TIdentifier : notnull { /// diff --git a/RGB.NET.Core/Update/Devices/UpdateQueue.cs b/RGB.NET.Core/Update/Devices/UpdateQueue.cs index 1cc5eca..bdd0868 100644 --- a/RGB.NET.Core/Update/Devices/UpdateQueue.cs +++ b/RGB.NET.Core/Update/Devices/UpdateQueue.cs @@ -10,7 +10,7 @@ namespace RGB.NET.Core; /// /// The type of the key used to identify some data. /// The type of the data. -public abstract class UpdateQueue : IUpdateQueue +public abstract class UpdateQueue : AbstractReferenceCounting, IUpdateQueue where TIdentifier : notnull { #region Properties & Fields @@ -112,8 +112,14 @@ public abstract class UpdateQueue : IUpdateQueue + /// + /// Disposes this queue. + /// Checks if any referencing objects are registered and if so, will return without disposing! + /// public virtual void Dispose() { + if (this.HasActiveReferences()) return; + _updateTrigger.Starting -= OnStartup; _updateTrigger.Update -= OnUpdate;