private ReadOnlyCollection <TKey> GetKeys() { ReadOnlyCollection <TKey> readOnlyCollection; int locksAcquired = 0; try { AcquireAllLocks(ref locksAcquired); var list = new List <TKey>(); for (int i = 0; i < _buckets.Length; i++) { for (ChoNode <TKey, TValue> node = _buckets[i]; node != null; node = node.Next) { list.Add(node.Key); } } readOnlyCollection = new ReadOnlyCollection <TKey>(list); } finally { ReleaseLocks(0, locksAcquired); } return(readOnlyCollection); }
public ChoNode(TKey key, TValue value, int hashcode, ChoNode <TKey, TValue> next) { Key = key; Value = value; Next = next; Hashcode = hashcode; }
public bool TryGetValue(TKey key, out TValue value) { int bucketNo; int lockNo; if (key == null) { throw new ArgumentNullException("key"); } ChoNode <TKey, TValue>[] buckets = _buckets; GetBucketAndLockNo(_comparer.GetHashCode(key), out bucketNo, out lockNo, buckets.Length); ChoNode <TKey, TValue> next = buckets[bucketNo]; Thread.MemoryBarrier(); while (next != null) { if (_comparer.Equals(next.Key, key)) { value = next.Value; return(true); } next = next.Next; } value = default(TValue); return(false); }
private bool TryRemoveInternal(TKey key, out TValue value, bool matchValue, TValue oldValue) { ChoNode <TKey, TValue>[] nodeArray; int bucketNo; int lockNo; Retry: nodeArray = _buckets; GetBucketAndLockNo(_comparer.GetHashCode(key), out bucketNo, out lockNo, nodeArray.Length); bool lockTaken = false; try { lockTaken = Monitor.TryEnter(_locks[lockNo]); if (nodeArray != _buckets) { goto Retry; } ChoNode <TKey, TValue> previousNode = null; for (ChoNode <TKey, TValue> currentNode = _buckets[bucketNo]; currentNode != null; currentNode = currentNode.Next) { if (_comparer.Equals(currentNode.Key, key)) { if (matchValue && !EqualityComparer <TValue> .Default.Equals(oldValue, currentNode.Value)) { value = default(TValue); return(false); } if (previousNode == null) { _buckets[bucketNo] = currentNode.Next; } else { previousNode.Next = currentNode.Next; } value = currentNode.Value; _countPerLock[lockNo] -= 1; return(true); } previousNode = currentNode; } } finally { if (lockTaken) { Monitor.Exit(_locks[lockNo]); } } value = default(TValue); return(false); }
private void CopyToPairs(KeyValuePair <TKey, TValue>[] array, int index) { ChoNode <TKey, TValue>[] buckets = _buckets; for (int i = 0; i < buckets.Length; i++) { for (ChoNode <TKey, TValue> node = buckets[i]; node != null; node = node.Next) { array[index] = new KeyValuePair <TKey, TValue>(node.Key, node.Value); index++; } } }
private void CopyToEntries(DictionaryEntry[] array, int index) { ChoNode <TKey, TValue>[] buckets = _buckets; for (int i = 0; i < buckets.Length; i++) { for (ChoNode <TKey, TValue> node = buckets[i]; node != null; node = node.Next) { array[index] = new DictionaryEntry(node.Key, node.Value); index++; } } }
private void GrowTable(ChoNode <TKey, TValue>[] buckets) { int locksAcquired = 0; try { AcquireLocks(0, 1, ref locksAcquired); if (buckets == _buckets) { int size; try { size = (buckets.Length * 2) + 1; while ((((size % 3) == 0) || ((size % 5) == 0)) || ((size % 7) == 0)) { size += 2; } } catch (OverflowException) { return; } var nodeArray = new ChoNode <TKey, TValue> [size]; int[] numArray = new int[_locks.Length]; AcquireLocks(1, _locks.Length, ref locksAcquired); for (int i = 0; i < buckets.Length; i++) { ChoNode <TKey, TValue> next; for (ChoNode <TKey, TValue> node = buckets[i]; node != null; node = next) { int bucketNo; int lockNo; next = node.Next; GetBucketAndLockNo(node.Hashcode, out bucketNo, out lockNo, nodeArray.Length); nodeArray[bucketNo] = new ChoNode <TKey, TValue>(node.Key, node.Value, node.Hashcode, nodeArray[bucketNo]); numArray[lockNo]++; } } _buckets = nodeArray; _countPerLock = numArray; } } finally { ReleaseLocks(0, locksAcquired); } }
private bool SetCurrent() { while (_index < _buckets.Length) { _currentNode = _buckets[_index]; Thread.MemoryBarrier(); while (_currentNode != null) { _current = new KeyValuePair <TKey, TValue>(_currentNode.Key, _currentNode.Value); _state = 1; return(true); } _index++; } return(false); }
public bool MoveNext() { switch (_state) { case 0: _state = -1; _buckets = _dictionary._buckets; _index = 0; if (SetCurrent()) { return(true); } break; case 1: _state = -1; _currentNode = _currentNode.Next; if (_currentNode != null) { _current = new KeyValuePair <TKey, TValue>(_currentNode.Key, _currentNode.Value); _state = 1; return(true); } _index++; if (SetCurrent()) { return(true); } break; } return(false); }
public bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue) { int bucketNo; int lockNo; ChoNode <TKey, TValue>[] nodeArray; if (key == null) { throw new ArgumentNullException("key"); } int hashCode = _comparer.GetHashCode(key); IEqualityComparer <TValue> comparer = EqualityComparer <TValue> .Default; Retry: nodeArray = _buckets; GetBucketAndLockNo(hashCode, out bucketNo, out lockNo, nodeArray.Length); bool lockTaken = false; try { lockTaken = Monitor.TryEnter(_locks[lockNo]); if (nodeArray != _buckets) { goto Retry; } ChoNode <TKey, TValue> previousNode = null; for (ChoNode <TKey, TValue> currentNode = nodeArray[bucketNo]; currentNode != null; currentNode = currentNode.Next) { if (_comparer.Equals(currentNode.Key, key)) { if (!comparer.Equals(currentNode.Value, comparisonValue)) { return(false); } var newNode = new ChoNode <TKey, TValue>(currentNode.Key, newValue, hashCode, currentNode.Next); if (previousNode == null) { nodeArray[bucketNo] = newNode; } else { previousNode.Next = newNode; } return(true); } previousNode = currentNode; } } finally { if (lockTaken) { Monitor.Exit(_locks[lockNo]); } } return(false); }
private bool TryAddInternal(TKey key, TValue value, bool updateIfExists, bool acquireLock, out TValue resultingValue) { int bucketNo; int lockNo; ChoNode <TKey, TValue>[] nodeArray; int hashCode = _comparer.GetHashCode(key); Retry: nodeArray = _buckets; GetBucketAndLockNo(hashCode, out bucketNo, out lockNo, nodeArray.Length); bool flag = false; bool lockTaken = false; try { if (acquireLock) { lockTaken = Monitor.TryEnter(_locks[lockNo]); } if (nodeArray != _buckets) { goto Retry; } ChoNode <TKey, TValue> previousNode = null; for (ChoNode <TKey, TValue> currentNode = nodeArray[bucketNo]; currentNode != null; currentNode = currentNode.Next) { if (_comparer.Equals(currentNode.Key, key)) { if (updateIfExists) { var newNode = new ChoNode <TKey, TValue>(currentNode.Key, value, hashCode, currentNode.Next); if (previousNode == null) { nodeArray[bucketNo] = newNode; } else { previousNode.Next = newNode; } resultingValue = value; } else { resultingValue = currentNode.Value; } return(false); } previousNode = currentNode; } nodeArray[bucketNo] = new ChoNode <TKey, TValue>(key, value, hashCode, nodeArray[bucketNo]); _countPerLock[lockNo] += 1; if (_countPerLock[lockNo] > (nodeArray.Length / _locks.Length)) { flag = true; } } finally { if (lockTaken) { Monitor.Exit(_locks[lockNo]); } } if (flag) { GrowTable(nodeArray); } resultingValue = value; return(true); }