diff --git a/SimSharp/Collections/SimplePriorityQueue.cs b/SimSharp/Collections/SimplePriorityQueue.cs index 6802422..9d17b0c 100644 --- a/SimSharp/Collections/SimplePriorityQueue.cs +++ b/SimSharp/Collections/SimplePriorityQueue.cs @@ -27,6 +27,7 @@ THE SOFTWARE. using System; using System.Collections; using System.Collections.Generic; +using System.Linq; namespace SimSharp { /// @@ -132,9 +133,7 @@ private class SimpleNode : GenericPriorityQueueNode { /// public int Count { get { - lock (_queue) { - return _queue.Count; - } + return _queue.Count; } } @@ -146,13 +145,11 @@ private class SimpleNode : GenericPriorityQueueNode { /// public TItem First { get { - lock (_queue) { - if (_queue.Count <= 0) { - throw new InvalidOperationException("Cannot call .First on an empty queue"); - } - - return _queue.First.Data; + if (_queue.Count <= 0) { + throw new InvalidOperationException("Cannot call .First on an empty queue"); } + + return _queue.First.Data; } } @@ -161,11 +158,9 @@ private class SimpleNode : GenericPriorityQueueNode { /// O(n) /// public void Clear() { - lock (_queue) { - _queue.Clear(); - _itemToNodesCache.Clear(); - _nullNodesCache.Clear(); - } + _queue.Clear(); + _itemToNodesCache.Clear(); + _nullNodesCache.Clear(); } /// @@ -173,12 +168,10 @@ private class SimpleNode : GenericPriorityQueueNode { /// O(1) /// public bool Contains(TItem item) { - lock (_queue) { - if (item == null) { - return _nullNodesCache.Count > 0; - } - return _itemToNodesCache.ContainsKey(item); + if (item == null) { + return _nullNodesCache.Count > 0; } + return _itemToNodesCache.ContainsKey(item); } /// @@ -187,24 +180,22 @@ private class SimpleNode : GenericPriorityQueueNode { /// O(log n) /// public TItem Dequeue() { - lock (_queue) { - if (_queue.Count <= 0) { - throw new InvalidOperationException("Cannot call Dequeue() on an empty queue"); - } - - SimpleNode node = _queue.Dequeue(); - RemoveFromNodeCache(node); - return node.Data; + if (_queue.Count <= 0) { + throw new InvalidOperationException("Cannot call Dequeue() on an empty queue"); } + + SimpleNode node = _queue.Dequeue(); + RemoveFromNodeCache(node); + return node.Data; } /// - /// Enqueue the item with the given priority, without calling lock(_queue) or AddToNodeCache(node) + /// Enqueue the item with the given priority, without calling AddToNodeCache(node) /// /// /// /// - private SimpleNode EnqueueNoLockOrCache(TItem item, TPriority priority) { + private SimpleNode EnqueueNoCache(TItem item, TPriority priority) { SimpleNode node = new SimpleNode(item); if (_queue.Count == _queue.MaxSize) { _queue.Resize(_queue.MaxSize * 2 + 1); @@ -220,17 +211,15 @@ private class SimpleNode : GenericPriorityQueueNode { /// O(log n) /// public void Enqueue(TItem item, TPriority priority) { - lock (_queue) { - IList nodes; - if (item == null) { - nodes = _nullNodesCache; - } else if (!_itemToNodesCache.TryGetValue(item, out nodes)) { - nodes = new List(); - _itemToNodesCache[item] = nodes; - } - SimpleNode node = EnqueueNoLockOrCache(item, priority); - nodes.Add(node); + IList nodes; + if (item == null) { + nodes = _nullNodesCache; + } else if (!_itemToNodesCache.TryGetValue(item, out nodes)) { + nodes = new List(); + _itemToNodesCache[item] = nodes; } + SimpleNode node = EnqueueNoCache(item, priority); + nodes.Add(node); } /// @@ -240,23 +229,21 @@ private class SimpleNode : GenericPriorityQueueNode { /// O(log n) /// public bool EnqueueWithoutDuplicates(TItem item, TPriority priority) { - lock (_queue) { - IList nodes; - if (item == null) { - if (_nullNodesCache.Count > 0) { - return false; - } - nodes = _nullNodesCache; - } else if (_itemToNodesCache.ContainsKey(item)) { + IList nodes; + if (item == null) { + if (_nullNodesCache.Count > 0) { return false; - } else { - nodes = new List(); - _itemToNodesCache[item] = nodes; } - SimpleNode node = EnqueueNoLockOrCache(item, priority); - nodes.Add(node); - return true; + nodes = _nullNodesCache; + } else if (_itemToNodesCache.ContainsKey(item)) { + return false; + } else { + nodes = new List(); + _itemToNodesCache[item] = nodes; } + SimpleNode node = EnqueueNoCache(item, priority); + nodes.Add(node); + return true; } /// @@ -266,27 +253,25 @@ private class SimpleNode : GenericPriorityQueueNode { /// O(log n) /// public void Remove(TItem item) { - lock (_queue) { - SimpleNode removeMe; - IList nodes; - if (item == null) { - if (_nullNodesCache.Count == 0) { - throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + item); - } - removeMe = _nullNodesCache[0]; - nodes = _nullNodesCache; - } else { - if (!_itemToNodesCache.TryGetValue(item, out nodes)) { - throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + item); - } - removeMe = nodes[0]; - if (nodes.Count == 1) { - _itemToNodesCache.Remove(item); - } + SimpleNode removeMe; + IList nodes; + if (item == null) { + if (_nullNodesCache.Count == 0) { + throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + item); + } + removeMe = _nullNodesCache[0]; + nodes = _nullNodesCache; + } else { + if (!_itemToNodesCache.TryGetValue(item, out nodes)) { + throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + item); + } + removeMe = nodes[0]; + if (nodes.Count == 1) { + _itemToNodesCache.Remove(item); } - _queue.Remove(removeMe); - nodes.Remove(removeMe); } + _queue.Remove(removeMe); + nodes.Remove(removeMe); } /// @@ -298,13 +283,11 @@ private class SimpleNode : GenericPriorityQueueNode { /// O(log n) /// public void UpdatePriority(TItem item, TPriority priority) { - lock (_queue) { - SimpleNode updateMe = GetExistingNode(item); - if (updateMe == null) { - throw new InvalidOperationException("Cannot call UpdatePriority() on a node which is not enqueued: " + item); - } - _queue.UpdatePriority(updateMe, priority); + SimpleNode updateMe = GetExistingNode(item); + if (updateMe == null) { + throw new InvalidOperationException("Cannot call UpdatePriority() on a node which is not enqueued: " + item); } + _queue.UpdatePriority(updateMe, priority); } /// @@ -316,13 +299,11 @@ private class SimpleNode : GenericPriorityQueueNode { /// O(1) /// public TPriority GetPriority(TItem item) { - lock (_queue) { - SimpleNode findMe = GetExistingNode(item); - if (findMe == null) { - throw new InvalidOperationException("Cannot call GetPriority() on a node which is not enqueued: " + item); - } - return findMe.Priority; + SimpleNode findMe = GetExistingNode(item); + if (findMe == null) { + throw new InvalidOperationException("Cannot call GetPriority() on a node which is not enqueued: " + item); } + return findMe.Priority; } #region Try* methods for multithreading @@ -331,15 +312,13 @@ private class SimpleNode : GenericPriorityQueueNode { /// Returns true if successful, false otherwise /// O(1) public bool TryFirst(out TItem first) { - lock (_queue) { - if (_queue.Count <= 0) { - first = default(TItem); - return false; - } - - first = _queue.First.Data; - return true; + if (_queue.Count <= 0) { + first = default(TItem); + return false; } + + first = _queue.First.Data; + return true; } /// @@ -349,17 +328,15 @@ private class SimpleNode : GenericPriorityQueueNode { /// O(log n) /// public bool TryDequeue(out TItem first) { - lock (_queue) { - if (_queue.Count <= 0) { - first = default(TItem); - return false; - } - - SimpleNode node = _queue.Dequeue(); - first = node.Data; - RemoveFromNodeCache(node); - return true; + if (_queue.Count <= 0) { + first = default(TItem); + return false; } + + SimpleNode node = _queue.Dequeue(); + first = node.Data; + RemoveFromNodeCache(node); + return true; } /// @@ -370,28 +347,26 @@ private class SimpleNode : GenericPriorityQueueNode { /// O(log n) /// public bool TryRemove(TItem item) { - lock (_queue) { - SimpleNode removeMe; - IList nodes; - if (item == null) { - if (_nullNodesCache.Count == 0) { - return false; - } - removeMe = _nullNodesCache[0]; - nodes = _nullNodesCache; - } else { - if (!_itemToNodesCache.TryGetValue(item, out nodes)) { - return false; - } - removeMe = nodes[0]; - if (nodes.Count == 1) { - _itemToNodesCache.Remove(item); - } + SimpleNode removeMe; + IList nodes; + if (item == null) { + if (_nullNodesCache.Count == 0) { + return false; + } + removeMe = _nullNodesCache[0]; + nodes = _nullNodesCache; + } else { + if (!_itemToNodesCache.TryGetValue(item, out nodes)) { + return false; + } + removeMe = nodes[0]; + if (nodes.Count == 1) { + _itemToNodesCache.Remove(item); } - _queue.Remove(removeMe); - nodes.Remove(removeMe); - return true; } + _queue.Remove(removeMe); + nodes.Remove(removeMe); + return true; } /// @@ -404,14 +379,12 @@ private class SimpleNode : GenericPriorityQueueNode { /// O(log n) /// public bool TryUpdatePriority(TItem item, TPriority priority) { - lock (_queue) { - SimpleNode updateMe = GetExistingNode(item); - if (updateMe == null) { - return false; - } - _queue.UpdatePriority(updateMe, priority); - return true; + SimpleNode updateMe = GetExistingNode(item); + if (updateMe == null) { + return false; } + _queue.UpdatePriority(updateMe, priority); + return true; } /// @@ -424,28 +397,18 @@ private class SimpleNode : GenericPriorityQueueNode { /// O(1) /// public bool TryGetPriority(TItem item, out TPriority priority) { - lock (_queue) { - SimpleNode findMe = GetExistingNode(item); - if (findMe == null) { - priority = default(TPriority); - return false; - } - priority = findMe.Priority; - return true; + SimpleNode findMe = GetExistingNode(item); + if (findMe == null) { + priority = default(TPriority); + return false; } + priority = findMe.Priority; + return true; } #endregion public IEnumerator GetEnumerator() { - List queueData = new List(); - lock (_queue) { - //Copy to a separate list because we don't want to 'yield return' inside a lock - foreach (var node in _queue) { - queueData.Add(node.Data); - } - } - - return queueData.GetEnumerator(); + return _queue.Select(x => x.Data).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { @@ -453,26 +416,24 @@ private class SimpleNode : GenericPriorityQueueNode { } public bool IsValidQueue() { - lock (_queue) { - // Check all items in cache are in the queue - foreach (IList nodes in _itemToNodesCache.Values) { - foreach (SimpleNode node in nodes) { - if (!_queue.Contains(node)) { - return false; - } - } - } - - // Check all items in queue are in cache - foreach (SimpleNode node in _queue) { - if (GetExistingNode(node.Data) == null) { + // Check all items in cache are in the queue + foreach (IList nodes in _itemToNodesCache.Values) { + foreach (SimpleNode node in nodes) { + if (!_queue.Contains(node)) { return false; } } + } - // Check queue structure itself - return _queue.IsValidQueue(); + // Check all items in queue are in cache + foreach (SimpleNode node in _queue) { + if (GetExistingNode(node.Data) == null) { + return false; + } } + + // Check queue structure itself + return _queue.IsValidQueue(); } } @@ -590,9 +551,7 @@ private class SimpleNode : GenericPriorityQueueNode, IComparable, IC /// public int Count { get { - lock (_queue) { - return _queue.Count; - } + return _queue.Count; } } @@ -604,13 +563,11 @@ private class SimpleNode : GenericPriorityQueueNode, IComparable, IC /// public TItem First { get { - lock (_queue) { - if (_queue.Count <= 0) { - throw new InvalidOperationException("Cannot call .First on an empty queue"); - } - - return _queue.First.Data; + if (_queue.Count <= 0) { + throw new InvalidOperationException("Cannot call .First on an empty queue"); } + + return _queue.First.Data; } } @@ -619,11 +576,9 @@ private class SimpleNode : GenericPriorityQueueNode, IComparable, IC /// O(n) /// public void Clear() { - lock (_queue) { - _queue.Clear(); - _itemToNodesCache.Clear(); - _nullNodesCache.Clear(); - } + _queue.Clear(); + _itemToNodesCache.Clear(); + _nullNodesCache.Clear(); } /// @@ -631,12 +586,10 @@ private class SimpleNode : GenericPriorityQueueNode, IComparable, IC /// O(1) /// public bool Contains(TItem item) { - lock (_queue) { - if (item == null) { - return _nullNodesCache.Count > 0; - } - return _itemToNodesCache.ContainsKey(item); + if (item == null) { + return _nullNodesCache.Count > 0; } + return _itemToNodesCache.ContainsKey(item); } /// @@ -645,23 +598,21 @@ private class SimpleNode : GenericPriorityQueueNode, IComparable, IC /// O(log n) /// public TItem Dequeue() { - lock (_queue) { - if (_queue.Count <= 0) { - throw new InvalidOperationException("Cannot call Dequeue() on an empty queue"); - } - - SimpleNode node = _queue.Dequeue(); - RemoveFromNodeCache(node); - return node.Data; + if (_queue.Count <= 0) { + throw new InvalidOperationException("Cannot call Dequeue() on an empty queue"); } + + SimpleNode node = _queue.Dequeue(); + RemoveFromNodeCache(node); + return node.Data; } /// - /// Enqueue the item with the given priority, without calling lock(_queue) or AddToNodeCache(node) + /// Enqueue the item with the given priority, without calling AddToNodeCache(node) /// /// /// - private SimpleNode EnqueueNoLockOrCache(TItem item) { + private SimpleNode EnqueueNoCache(TItem item) { SimpleNode node = new SimpleNode(item, _comparer); if (_queue.Count == _queue.MaxSize) { _queue.Resize(_queue.MaxSize * 2 + 1); @@ -677,17 +628,15 @@ private class SimpleNode : GenericPriorityQueueNode, IComparable, IC /// O(log n) /// public void Enqueue(TItem item) { - lock (_queue) { - IList nodes; - if (item == null) { - nodes = _nullNodesCache; - } else if (!_itemToNodesCache.TryGetValue(item, out nodes)) { - nodes = new List(); - _itemToNodesCache[item] = nodes; - } - SimpleNode node = EnqueueNoLockOrCache(item); - nodes.Add(node); + IList nodes; + if (item == null) { + nodes = _nullNodesCache; + } else if (!_itemToNodesCache.TryGetValue(item, out nodes)) { + nodes = new List(); + _itemToNodesCache[item] = nodes; } + SimpleNode node = EnqueueNoCache(item); + nodes.Add(node); } /// @@ -697,23 +646,21 @@ private class SimpleNode : GenericPriorityQueueNode, IComparable, IC /// O(log n) /// public bool EnqueueWithoutDuplicates(TItem item) { - lock (_queue) { - IList nodes; - if (item == null) { - if (_nullNodesCache.Count > 0) { - return false; - } - nodes = _nullNodesCache; - } else if (_itemToNodesCache.ContainsKey(item)) { + IList nodes; + if (item == null) { + if (_nullNodesCache.Count > 0) { return false; - } else { - nodes = new List(); - _itemToNodesCache[item] = nodes; } - SimpleNode node = EnqueueNoLockOrCache(item); - nodes.Add(node); - return true; + nodes = _nullNodesCache; + } else if (_itemToNodesCache.ContainsKey(item)) { + return false; + } else { + nodes = new List(); + _itemToNodesCache[item] = nodes; } + SimpleNode node = EnqueueNoCache(item); + nodes.Add(node); + return true; } /// @@ -723,27 +670,25 @@ private class SimpleNode : GenericPriorityQueueNode, IComparable, IC /// O(log n) /// public void Remove(TItem item) { - lock (_queue) { - SimpleNode removeMe; - IList nodes; - if (item == null) { - if (_nullNodesCache.Count == 0) { - throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + item); - } - removeMe = _nullNodesCache[0]; - nodes = _nullNodesCache; - } else { - if (!_itemToNodesCache.TryGetValue(item, out nodes)) { - throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + item); - } - removeMe = nodes[0]; - if (nodes.Count == 1) { - _itemToNodesCache.Remove(item); - } + SimpleNode removeMe; + IList nodes; + if (item == null) { + if (_nullNodesCache.Count == 0) { + throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + item); + } + removeMe = _nullNodesCache[0]; + nodes = _nullNodesCache; + } else { + if (!_itemToNodesCache.TryGetValue(item, out nodes)) { + throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + item); + } + removeMe = nodes[0]; + if (nodes.Count == 1) { + _itemToNodesCache.Remove(item); } - _queue.Remove(removeMe); - nodes.Remove(removeMe); } + _queue.Remove(removeMe); + nodes.Remove(removeMe); } /// @@ -755,13 +700,11 @@ private class SimpleNode : GenericPriorityQueueNode, IComparable, IC /// O(log n) /// public void UpdatePriority(TItem item) { - lock (_queue) { - SimpleNode updateMe = GetExistingNode(item); - if (updateMe == null) { - throw new InvalidOperationException("Cannot call UpdatePriority() on a node which is not enqueued: " + item); - } - _queue.UpdatePriority(updateMe); + SimpleNode updateMe = GetExistingNode(item); + if (updateMe == null) { + throw new InvalidOperationException("Cannot call UpdatePriority() on a node which is not enqueued: " + item); } + _queue.UpdatePriority(updateMe); } #region Try* methods for multithreading @@ -770,15 +713,13 @@ private class SimpleNode : GenericPriorityQueueNode, IComparable, IC /// Returns true if successful, false otherwise /// O(1) public bool TryFirst(out TItem first) { - lock (_queue) { - if (_queue.Count <= 0) { - first = default(TItem); - return false; - } - - first = _queue.First.Data; - return true; + if (_queue.Count <= 0) { + first = default(TItem); + return false; } + + first = _queue.First.Data; + return true; } /// @@ -788,17 +729,15 @@ private class SimpleNode : GenericPriorityQueueNode, IComparable, IC /// O(log n) /// public bool TryDequeue(out TItem first) { - lock (_queue) { - if (_queue.Count <= 0) { - first = default(TItem); - return false; - } - - SimpleNode node = _queue.Dequeue(); - first = node.Data; - RemoveFromNodeCache(node); - return true; + if (_queue.Count <= 0) { + first = default(TItem); + return false; } + + SimpleNode node = _queue.Dequeue(); + first = node.Data; + RemoveFromNodeCache(node); + return true; } /// @@ -809,28 +748,26 @@ private class SimpleNode : GenericPriorityQueueNode, IComparable, IC /// O(log n) /// public bool TryRemove(TItem item) { - lock (_queue) { - SimpleNode removeMe; - IList nodes; - if (item == null) { - if (_nullNodesCache.Count == 0) { - return false; - } - removeMe = _nullNodesCache[0]; - nodes = _nullNodesCache; - } else { - if (!_itemToNodesCache.TryGetValue(item, out nodes)) { - return false; - } - removeMe = nodes[0]; - if (nodes.Count == 1) { - _itemToNodesCache.Remove(item); - } + SimpleNode removeMe; + IList nodes; + if (item == null) { + if (_nullNodesCache.Count == 0) { + return false; + } + removeMe = _nullNodesCache[0]; + nodes = _nullNodesCache; + } else { + if (!_itemToNodesCache.TryGetValue(item, out nodes)) { + return false; + } + removeMe = nodes[0]; + if (nodes.Count == 1) { + _itemToNodesCache.Remove(item); } - _queue.Remove(removeMe); - nodes.Remove(removeMe); - return true; } + _queue.Remove(removeMe); + nodes.Remove(removeMe); + return true; } /// @@ -843,27 +780,17 @@ private class SimpleNode : GenericPriorityQueueNode, IComparable, IC /// O(log n) /// public bool TryUpdatePriority(TItem item) { - lock (_queue) { - SimpleNode updateMe = GetExistingNode(item); - if (updateMe == null) { - return false; - } - _queue.UpdatePriority(updateMe); - return true; + SimpleNode updateMe = GetExistingNode(item); + if (updateMe == null) { + return false; } + _queue.UpdatePriority(updateMe); + return true; } #endregion public IEnumerator GetEnumerator() { - List queueData = new List(); - lock (_queue) { - //Copy to a separate list because we don't want to 'yield return' inside a lock - foreach (var node in _queue) { - queueData.Add(node.Data); - } - } - - return queueData.GetEnumerator(); + return _queue.Select(x => x.Data).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { @@ -871,26 +798,24 @@ private class SimpleNode : GenericPriorityQueueNode, IComparable, IC } public bool IsValidQueue() { - lock (_queue) { - // Check all items in cache are in the queue - foreach (IList nodes in _itemToNodesCache.Values) { - foreach (SimpleNode node in nodes) { - if (!_queue.Contains(node)) { - return false; - } - } - } - - // Check all items in queue are in cache - foreach (SimpleNode node in _queue) { - if (GetExistingNode(node.Data) == null) { + // Check all items in cache are in the queue + foreach (IList nodes in _itemToNodesCache.Values) { + foreach (SimpleNode node in nodes) { + if (!_queue.Contains(node)) { return false; } } + } - // Check queue structure itself - return _queue.IsValidQueue(); + // Check all items in queue are in cache + foreach (SimpleNode node in _queue) { + if (GetExistingNode(node.Data) == null) { + return false; + } } + + // Check queue structure itself + return _queue.IsValidQueue(); } } } \ No newline at end of file