using System; using System.Collections.Generic; using System.Linq; namespace RGB.NET.Core { /// /// Represents a generic update queue. /// /// The type of the key used to identify some data. /// The type of the data. public abstract class UpdateQueue : IDisposable where TIdentifier : notnull { #region Properties & Fields private readonly object _dataLock = new(); private readonly IDeviceUpdateTrigger _updateTrigger; private Dictionary? _currentDataSet; #endregion #region Constructors /// /// Initializes a new instance of the class. /// /// The causing this queue to update. protected UpdateQueue(IDeviceUpdateTrigger updateTrigger) { this._updateTrigger = updateTrigger; _updateTrigger.Starting += OnStartup; _updateTrigger.Update += OnUpdate; } #endregion #region Methods /// /// Event handler for the -event. /// /// The causing this update. /// provided by the trigger. protected virtual void OnUpdate(object? sender, CustomUpdateData customData) { Dictionary dataSet; lock (_dataLock) { if (_currentDataSet == null) return; dataSet = _currentDataSet; _currentDataSet = null; } if (dataSet.Count != 0) Update(dataSet); } /// /// Event handler for the -event. /// /// The starting . /// provided by the trigger. protected virtual void OnStartup(object? sender, CustomUpdateData customData) { } /// /// Performs the update this queue is responsible for. /// /// The set of data that needs to be updated. protected abstract void Update(Dictionary dataSet); /// /// Sets or merges the provided data set in the current dataset and notifies the trigger that there is new data available. /// /// The set of data. // ReSharper disable once MemberCanBeProtected.Global public virtual void SetData(Dictionary dataSet) { if (dataSet.Count == 0) return; lock (_dataLock) { if (_currentDataSet == null) _currentDataSet = dataSet; else { foreach ((TIdentifier key, TData value) in dataSet) _currentDataSet[key] = value; } } _updateTrigger.TriggerHasData(); } /// /// Resets the current data set. /// public virtual void Reset() { lock (_dataLock) _currentDataSet = null; } /// public virtual void Dispose() { _updateTrigger.Starting -= OnStartup; _updateTrigger.Update -= OnUpdate; Reset(); } #endregion } /// /// Represents a generic using an object as the key and a color as the value. /// public abstract class UpdateQueue : UpdateQueue { #region Constructors /// protected UpdateQueue(IDeviceUpdateTrigger updateTrigger) : base(updateTrigger) { } #endregion #region Methods /// /// Calls for a data set created out of the provided list of . /// /// public void SetData(IEnumerable leds) => SetData(leds.ToDictionary(x => x.CustomData ?? x.Id, x => x.Color)); #endregion } }