/// <summary> /// Removes the data at the specified key location. /// </summary> /// <param name="key">The key.</param> public void Remove(TKey key) { try { writeLock.Enter(); HashtableNode <TKey, TData>[] table = array; var initialHash = Math.Abs(GetHashCode_HashTable <TKey> .GetHashCode(key)) % table.Length; var hash = initialHash; do { HashtableNode <TKey, TData> n = table[hash]; if (n.Token == HashtableToken.Empty) { return; } if (n.Token == HashtableToken.Deleted || !KeyComparer.Equals(key, n.Key)) { hash = (hash + 1) % table.Length; } else { table[hash] = DeletedNode; } } while (hash != initialHash); // MartinG@DigitalRune: Stop when all entries are checked! } finally { writeLock.Exit(); } }
private bool Find(TKey key, out HashtableNode <TKey, TData> node) { node = new HashtableNode <TKey, TData>(); var table = array; var initialHash = Math.Abs(GetHashCode_HashTable <TKey> .GetHashCode(key)) % table.Length; var hash = initialHash; do { HashtableNode <TKey, TData> n = table[hash]; if (n.Token == HashtableToken.Empty) { return(false); } if (n.Token == HashtableToken.Deleted || !KeyComparer.Equals(key, n.Key)) { hash = (hash + 1) % table.Length; } else { node = n; return(true); } } while (hash != initialHash); return(false); }
private bool Insert(HashtableNode <TKey, TData>[] table, TKey key, TData data) { var initialHash = Math.Abs(GetHashCode_HashTable <TKey> .GetHashCode(key)) % table.Length; var hash = initialHash; bool inserted = false; do { var node = table[hash]; // if node is empty, or marked with a tombstone if (node.Token == HashtableToken.Empty || node.Token == HashtableToken.Deleted || KeyComparer.Equals(key, node.Key)) { table[hash] = new HashtableNode <TKey, TData>() { Key = key, Data = data, Token = HashtableToken.Used }; inserted = true; break; } else { hash = (hash + 1) % table.Length; } } while (hash != initialHash); return(inserted); }
private void Resize() { var newArray = new HashtableNode <TKey, TData> [array.Length * 2]; for (int i = 0; i < array.Length; i++) { var item = array[i]; if (item.Token == HashtableToken.Used) { Insert(newArray, item.Key, item.Data); } } array = newArray; }
/// <summary> /// Sets the value of the item at the specified key location. /// This is only guaranteed to work correctly if no other thread is modifying the same key. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The new value.</param> public void UnsafeSet(TKey key, TData value) { HashtableNode <TKey, TData>[] table; bool inserted = false; do { table = array; var initialHash = Math.Abs(GetHashCode_HashTable <TKey> .GetHashCode(key)) % table.Length; var hash = initialHash; do { var node = table[hash]; if (KeyComparer.Equals(key, node.Key)) { table[hash] = new HashtableNode <TKey, TData>() { Key = key, Data = value, Token = HashtableToken.Used }; inserted = true; break; } else { hash = (hash + 1) % table.Length; } } while (hash != initialHash); } while (table != array); // MartinG@DigitalRune: I have moved the Add() outside the loop because it uses a // write-lock and the loop above should run without locks. if (!inserted) { Add(key, value); } }