diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a54a88..18db580 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -149,6 +149,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Better VC-4 support for IcdConsole - JSON refactoring for simpler deserialization +## [8.8.0] - 2020-01-23 +### Added + - Added an overload to PriorityQueue for determing the de-duplication behaviour + ## [8.7.2] - 2019-10-29 ### Changed - Fixed a bug with PriorityQueue de-duplication where a new command would be inserted in the wrong position diff --git a/ICD.Common.Utils/Collections/PriorityQueue.cs b/ICD.Common.Utils/Collections/PriorityQueue.cs index 34ab00d..2143ae7 100644 --- a/ICD.Common.Utils/Collections/PriorityQueue.cs +++ b/ICD.Common.Utils/Collections/PriorityQueue.cs @@ -79,6 +79,20 @@ namespace ICD.Common.Utils.Collections m_Count++; } + /// + /// Adds the item to the queue with the given priority at the given index. + /// + /// + /// + /// + [PublicAPI] + public void Enqueue([CanBeNull] T item, int priority, int position) + { + m_PriorityToQueue.GetOrAddNew(priority, ()=> new List()) + .Insert(position, item); + m_Count++; + } + /// /// Enqueues the item at the beginning of the queue. /// @@ -121,6 +135,27 @@ namespace ICD.Common.Utils.Collections if (remove == null) throw new ArgumentNullException("remove"); + EnqueueRemove(item, remove, priority, false); + } + + /// + /// Removes any items in the queue matching the predicate. + /// Appends the given item at the end of the given priority level. + /// This is useful for reducing duplication, or replacing items with something more pertinent. + /// + /// + /// + /// + /// + [PublicAPI] + public void EnqueueRemove([CanBeNull] T item, [NotNull] Func remove, int priority, bool deDuplicateToEndOfQueue) + { + if (remove == null) + throw new ArgumentNullException("remove"); + + int lowestMatchingPriority = int.MaxValue; + int? firstMatchingIndex = null; + foreach (KeyValuePair> kvp in m_PriorityToQueue.ToArray()) { int[] removeIndices = @@ -129,6 +164,12 @@ namespace ICD.Common.Utils.Collections .Reverse() .ToArray(); + if (removeIndices.Any() && kvp.Key < lowestMatchingPriority ) + { + lowestMatchingPriority = kvp.Key; + firstMatchingIndex = removeIndices.Last(); + } + foreach (int removeIndex in removeIndices) { kvp.Value.RemoveAt(removeIndex); @@ -139,7 +180,16 @@ namespace ICD.Common.Utils.Collections m_PriorityToQueue.Remove(kvp.Key); } - Enqueue(item, priority); + + if(deDuplicateToEndOfQueue) + Enqueue(item, priority); + else + { + if(firstMatchingIndex == null) + Enqueue(item, lowestMatchingPriority); + else + Enqueue(item, lowestMatchingPriority, firstMatchingIndex.Value); + } } /// diff --git a/ICD.Common.Utils/Extensions/DictionaryExtensions.cs b/ICD.Common.Utils/Extensions/DictionaryExtensions.cs index 7bcb3df..33db000 100644 --- a/ICD.Common.Utils/Extensions/DictionaryExtensions.cs +++ b/ICD.Common.Utils/Extensions/DictionaryExtensions.cs @@ -144,15 +144,15 @@ namespace ICD.Common.Utils.Extensions /// [PublicAPI] public static TValue GetOrAddNew([NotNull] this IDictionary extends, - [NotNull] TKey key) + [NotNull] TKey key) where TValue : new() { if (extends == null) throw new ArgumentNullException("extends"); -// ReSharper disable CompareNonConstrainedGenericWithNull + // ReSharper disable CompareNonConstrainedGenericWithNull if (key == null) -// ReSharper restore CompareNonConstrainedGenericWithNull + // ReSharper restore CompareNonConstrainedGenericWithNull throw new ArgumentNullException("key"); return extends.GetOrAddNew(key, () => ReflectionUtils.CreateInstance()); @@ -169,15 +169,15 @@ namespace ICD.Common.Utils.Extensions /// [PublicAPI] public static TValue GetOrAddNew([NotNull] this IDictionary extends, - [NotNull] TKey key, - [NotNull] Func valueFunc) + [NotNull] TKey key, + [NotNull] Func valueFunc) { if (extends == null) throw new ArgumentNullException("extends"); -// ReSharper disable CompareNonConstrainedGenericWithNull + // ReSharper disable CompareNonConstrainedGenericWithNull if (key == null) -// ReSharper restore CompareNonConstrainedGenericWithNull + // ReSharper restore CompareNonConstrainedGenericWithNull throw new ArgumentNullException("key"); if (valueFunc == null)