private static long IntHashTrieAdd(ref IntHashTrie <string> trie, int[] keys, int key, string value) { var ignored = "ignored"; var treeTime = Stopwatch.StartNew(); for (var i = 0; i < keys.Length; i++) { Interlocked.Exchange(ref trie, trie.AddOrUpdate(keys[i], ignored)); } Interlocked.Exchange(ref trie, trie.AddOrUpdate(key, value)); treeTime.Stop(); GC.Collect(); return(treeTime.ElapsedMilliseconds); }
public IntHashTrie <V> AddOrUpdate(int hash, V value, Update <V> updateValue = null) { var index = hash & 31; // index from 0 to 31 var restOfHash = hash >> 5; var newNodes = new object[32]; if (_indexBitmap == 0) { newNodes[index] = restOfHash == 0 ? (object)value : HashTrieNode <V> .Empty.AddOrUpdate(restOfHash, value); return(new IntHashTrie <V>(1u << index, newNodes)); } Array.Copy(_nodes, 0, newNodes, 0, newNodes.Length); if ((_indexBitmap & (1u << index)) == 0) // no nodes at the index, could be inserted. { newNodes[index] = restOfHash == 0 ? (object)value : Empty.AddOrUpdate(restOfHash, value); return(new IntHashTrie <V>(_indexBitmap | (1u << index), newNodes)); } var updatedNode = _nodes[index]; if (updatedNode is HashTrieNode <V> ) { updatedNode = ((HashTrieNode <V>)updatedNode).AddOrUpdate(restOfHash, value, updateValue); } else if (restOfHash != 0) // if we need to update value with node we will move value down to new node sub-nodes at index 0. { updatedNode = new HashTrieNode <V>(1u, updatedNode).AddOrUpdate(restOfHash, value, updateValue); } else // here the actual update should go, cause old and new nodes contain values. { updatedNode = updateValue == null ? value : updateValue((V)updatedNode, value); } newNodes[index] = updatedNode; return(new IntHashTrie <V>(_indexBitmap, newNodes)); }