mirror of
https://github.com/DarthAffe/RGB.NET.git
synced 2025-12-12 17:48:31 +00:00
Added reference counting to update queues to prevent premature disposes when used in multiple devices
This commit is contained in:
parent
39cfcdb367
commit
d054d16c10
@ -85,6 +85,8 @@ public abstract class AbstractRGBDevice<TDeviceInfo> : Placeable, IRGBDevice<TDe
|
|||||||
{
|
{
|
||||||
this.DeviceInfo = deviceInfo;
|
this.DeviceInfo = deviceInfo;
|
||||||
this.UpdateQueue = updateQueue;
|
this.UpdateQueue = updateQueue;
|
||||||
|
|
||||||
|
UpdateQueue.AddReferencingObject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -157,7 +159,12 @@ public abstract class AbstractRGBDevice<TDeviceInfo> : Placeable, IRGBDevice<TDe
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual void Dispose()
|
public virtual void Dispose()
|
||||||
{
|
{
|
||||||
try { UpdateQueue.Dispose(); } catch { /* :( */ }
|
try
|
||||||
|
{
|
||||||
|
UpdateQueue.RemoveReferencingObject(this);
|
||||||
|
UpdateQueue.Dispose();
|
||||||
|
}
|
||||||
|
catch { /* :( */ }
|
||||||
try { LedMapping.Clear(); } catch { /* this really shouldn't happen */ }
|
try { LedMapping.Clear(); } catch { /* this really shouldn't happen */ }
|
||||||
|
|
||||||
IdGenerator.ResetCounter(GetType().Assembly);
|
IdGenerator.ResetCounter(GetType().Assembly);
|
||||||
|
|||||||
6
RGB.NET.Core/Extensions/ReferenceCountingExtension.cs
Normal file
6
RGB.NET.Core/Extensions/ReferenceCountingExtension.cs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
namespace RGB.NET.Core;
|
||||||
|
|
||||||
|
public static class ReferenceCountingExtension
|
||||||
|
{
|
||||||
|
public static bool HasActiveReferences(this IReferenceCounting target) => target.ActiveReferenceCount > 0;
|
||||||
|
}
|
||||||
41
RGB.NET.Core/Misc/AbstractReferenceCounting.cs
Normal file
41
RGB.NET.Core/Misc/AbstractReferenceCounting.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace RGB.NET.Core;
|
||||||
|
|
||||||
|
public abstract class AbstractReferenceCounting : IReferenceCounting
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
private readonly HashSet<object> _referencingObjects = new();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public int ActiveReferenceCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (_referencingObjects)
|
||||||
|
return _referencingObjects.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void AddReferencingObject(object obj)
|
||||||
|
{
|
||||||
|
lock (_referencingObjects)
|
||||||
|
if (!_referencingObjects.Contains(obj))
|
||||||
|
_referencingObjects.Add(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void RemoveReferencingObject(object obj)
|
||||||
|
{
|
||||||
|
lock (_referencingObjects)
|
||||||
|
_referencingObjects.Remove(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
21
RGB.NET.Core/Misc/IReferenceCounting.cs
Normal file
21
RGB.NET.Core/Misc/IReferenceCounting.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
namespace RGB.NET.Core;
|
||||||
|
|
||||||
|
public interface IReferenceCounting
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the amount of currently registered referencing objects.
|
||||||
|
/// </summary>
|
||||||
|
public int ActiveReferenceCount { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the given object to the list of referencing objects.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">The object to add.</param>
|
||||||
|
public void AddReferencingObject(object obj);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the given object from the list of referencing objects.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">The object to remove.</param>
|
||||||
|
public void RemoveReferencingObject(object obj);
|
||||||
|
}
|
||||||
@ -16,6 +16,7 @@
|
|||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=helper/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=helper/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=ids/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=ids/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=leds/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=leds/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=misc/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=mvvm/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=mvvm/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=positioning/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=positioning/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=rendering/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=rendering/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
|||||||
@ -8,7 +8,7 @@ namespace RGB.NET.Core;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TIdentifier">The identifier used to identify the data processed by this queue.</typeparam>
|
/// <typeparam name="TIdentifier">The identifier used to identify the data processed by this queue.</typeparam>
|
||||||
/// <typeparam name="TData">The type of the data processed by this queue.</typeparam>
|
/// <typeparam name="TData">The type of the data processed by this queue.</typeparam>
|
||||||
public interface IUpdateQueue<TIdentifier, TData> : IDisposable
|
public interface IUpdateQueue<TIdentifier, TData> : IReferenceCounting, IDisposable
|
||||||
where TIdentifier : notnull
|
where TIdentifier : notnull
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -10,7 +10,7 @@ namespace RGB.NET.Core;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TIdentifier">The type of the key used to identify some data.</typeparam>
|
/// <typeparam name="TIdentifier">The type of the key used to identify some data.</typeparam>
|
||||||
/// <typeparam name="TData">The type of the data.</typeparam>
|
/// <typeparam name="TData">The type of the data.</typeparam>
|
||||||
public abstract class UpdateQueue<TIdentifier, TData> : IUpdateQueue<TIdentifier, TData>
|
public abstract class UpdateQueue<TIdentifier, TData> : AbstractReferenceCounting, IUpdateQueue<TIdentifier, TData>
|
||||||
where TIdentifier : notnull
|
where TIdentifier : notnull
|
||||||
{
|
{
|
||||||
#region Properties & Fields
|
#region Properties & Fields
|
||||||
@ -112,8 +112,14 @@ public abstract class UpdateQueue<TIdentifier, TData> : IUpdateQueue<TIdentifier
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
/// <summary>
|
||||||
|
/// Disposes this queue.
|
||||||
|
/// Checks if any referencing objects are registered and if so, will return without disposing!
|
||||||
|
/// </summary>
|
||||||
public virtual void Dispose()
|
public virtual void Dispose()
|
||||||
{
|
{
|
||||||
|
if (this.HasActiveReferences()) return;
|
||||||
|
|
||||||
_updateTrigger.Starting -= OnStartup;
|
_updateTrigger.Starting -= OnStartup;
|
||||||
_updateTrigger.Update -= OnUpdate;
|
_updateTrigger.Update -= OnUpdate;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user