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);
        }
Exemple #2
0
 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);
        }