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); } } } }
/// <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); }
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); } }
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); }