Exemple #1
0
        public Boolean TryUpdate(Byte[] key, Block newValue, Block comparisonValue)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            IEqualityComparer <Block> @default = EqualityComparer <Block> .Default;

            while (true)
            {
                var tables   = _table;
                var comparer = tables.Comparer;
                var hashCode = comparer.GetHashCode(key);
                GetBucketAndLockNo(hashCode, out var num, out var num2, tables.Buckets.Length, tables.Locks.Length);
                lock (tables.Locks[num2])
                {
                    if (tables == _table)
                    {
                        DbNode node = null;
                        for (var node2 = tables.Buckets[num]; node2 != null; node2 = node2.Next)
                        {
                            if (comparer.Equals(node2.Key, key))
                            {
                                if (@default.Equals(node2.Value, comparisonValue))
                                {
                                    var node3 = new DbNode(node2.Key, newValue, hashCode, node2.Next);
                                    if (node == null)
                                    {
                                        tables.Buckets[num] = node3;
                                    }
                                    else
                                    {
                                        node.Next = node3;
                                    }

                                    return(true);
                                }
                                return(false);
                            }
                            node = node2;
                        }
                        return(false);
                    }
                }
            }
        }
Exemple #2
0
        /// <summary>尝试移除并返回具有指定键的值</summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public Boolean TryRemove(Byte[] key, out Block value)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            while (true)
            {
                var tables   = _table;
                var comparer = tables.Comparer;
                GetBucketAndLockNo(comparer.GetHashCode(key), out var num, out var num2, tables.Buckets.Length, tables.Locks.Length);
                lock (tables.Locks[num2])
                {
                    if (tables == _table)
                    {
                        DbNode node = null;
                        for (var node2 = tables.Buckets[num]; node2 != null; node2 = node2.Next)
                        {
                            if (comparer.Equals(node2.Key, key))
                            {
                                if (node == null)
                                {
                                    Volatile.Write(ref tables.Buckets[num], node2.Next);
                                }
                                else
                                {
                                    node.Next = node2.Next;
                                }
                                value = node2.Value;
                                tables.CountPerLock[num2]--;
                                return(true);
                            }
                            node = node2;
                        }
                        break;
                    }
                }
            }
            value = default(Block);
            return(false);
        }
Exemple #3
0
        private void GrowTable(Bucket tables, IEqualityComparer <Byte[]> newComparer, Boolean regenerateHashKeys, Int32 rehashCount)
        {
            var locksAcquired = 0;

            try
            {
                AcquireLocks(0, 1, ref locksAcquired);
                if (regenerateHashKeys && rehashCount == _keyRehashCount)
                {
                    tables = _table;
                }
                else
                {
                    if (tables != _table)
                    {
                        return;
                    }
                    Int64 num = 0;
                    for (var index = 0; index < tables.CountPerLock.Length; ++index)
                    {
                        num += tables.CountPerLock[index];
                    }
                    if (num < tables.Buckets.Length / 4)
                    {
                        _budget = 2 * _budget;
                        if (_budget >= 0)
                        {
                            return;
                        }
                        _budget = Int32.MaxValue;
                        return;
                    }
                }
                var length1 = 0;
                var flag    = false;
                try
                {
                    length1 = checked (tables.Buckets.Length * 2 + 1);
                    while (length1 % 3 == 0 || length1 % 5 == 0 || length1 % 7 == 0)
                    {
                        checked { length1 += 2; }
                    }
                    if (length1 > 2146435071)
                    {
                        flag = true;
                    }
                }
                catch (OverflowException)
                {
                    flag = true;
                }
                if (flag)
                {
                    length1 = 2146435071;
                    _budget = Int32.MaxValue;
                }
                AcquireLocks(1, tables.Locks.Length, ref locksAcquired);
                var locks = tables.Locks;
                if (tables.Locks.Length < 1024)
                {
                    locks = new Object[tables.Locks.Length * 2];
                    Array.Copy(tables.Locks, locks, tables.Locks.Length);
                    for (var length2 = tables.Locks.Length; length2 < locks.Length; ++length2)
                    {
                        locks[length2] = new Object();
                    }
                }
                var    buckets      = new DbNode[length1];
                var    countPerLock = new Int32[locks.Length];
                DbNode next;
                for (var index = 0; index < tables.Buckets.Length; ++index)
                {
                    for (var node = tables.Buckets[index]; node != null; node = next)
                    {
                        next = node.Next;
                        var hashcode = node.HashCode;
                        if (regenerateHashKeys)
                        {
                            hashcode = newComparer.GetHashCode(node.Key);
                        }
                        GetBucketAndLockNo(hashcode, out var bucketNo, out var lockNo, buckets.Length, locks.Length);
                        buckets[bucketNo] = new DbNode(node.Key, node.Value, hashcode, buckets[bucketNo]);
                        checked { ++countPerLock[lockNo]; }
                    }
                }
                if (regenerateHashKeys)
                {
                    _keyRehashCount = _keyRehashCount + 1;
                }
                _budget = Math.Max(1, buckets.Length / locks.Length);
                _table  = new Bucket(buckets, locks, countPerLock, newComparer);
            }
            finally
            {
                ReleaseLocks(0, locksAcquired);
            }
        }
Exemple #4
0
        private Boolean TryAddInternal(Byte[] key, Block value, Boolean updateIfExists, Boolean acquireLock, out Block resultingValue)
        {
            Bucket tables;
            IEqualityComparer <Byte[]> comparer;
            Boolean flag;

            //Boolean flag3;
            while (true)
            {
                tables   = _table;
                comparer = tables.Comparer;
                var hashCode = comparer.GetHashCode(key);
                GetBucketAndLockNo(hashCode, out var num, out var num2, tables.Buckets.Length, tables.Locks.Length);
                flag = false;
                var flag2 = false;
                //flag3 = false;
                try
                {
                    if (acquireLock)
                    {
                        Monitor.Enter(tables.Locks[num2], ref flag2);
                    }

                    if (tables == _table)
                    {
                        var    num3 = 0;
                        DbNode node = null;
                        for (var node2 = tables.Buckets[num]; node2 != null; node2 = node2.Next)
                        {
                            if (comparer.Equals(node2.Key, key))
                            {
                                if (updateIfExists)
                                {
                                    var node3 = new DbNode(node2.Key, value, hashCode, node2.Next);
                                    if (node == null)
                                    {
                                        tables.Buckets[num] = node3;
                                    }
                                    else
                                    {
                                        node.Next = node3;
                                    }

                                    resultingValue = value;
                                }
                                else
                                {
                                    resultingValue = node2.Value;
                                }
                                return(false);
                            }
                            node = node2;
                            num3++;
                        }
                        //if (num3 > 100 && HashHelpers.IsWellKnownEqualityComparer(comparer))
                        //{
                        //    flag = true;
                        //    flag3 = true;
                        //}
                        Volatile.Write(ref tables.Buckets[num], new DbNode(key, value, hashCode, tables.Buckets[num]));
                        checked
                        {
                            tables.CountPerLock[num2]++;
                            if (tables.CountPerLock[num2] > _budget)
                            {
                                flag = true;
                            }
                            break;
                        }
                    }
                }
                finally
                {
                    if (flag2)
                    {
                        Monitor.Exit(tables.Locks[num2]);
                    }
                }
            }
            if (flag)
            {
                //if (flag3)
                //{
                //    GrowTable(tables, (IEqualityComparer<Byte[]>)HashHelpers.GetRandomizedEqualityComparer(comparer), true, m_keyRehashCount);
                //}
                //else
                {
                    GrowTable(tables, tables.Comparer, false, _keyRehashCount);
                }
            }
            resultingValue = value;
            return(true);
        }