Esempio n. 1
0
        private static long HashTrieAdd <V>(ref HashTrie <V> trie, int[] keys, int key, V value)
        {
            var ignored  = default(V);
            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);
        }
Esempio n. 2
0
        private static long TrieAdd <V>(ref HashTrie <Type, V> tree, Type[] keys, Type key, V value)
        {
            var ignored  = default(V);
            var treeTime = Stopwatch.StartNew();

            for (var i = 0; i < keys.Length; i++)
            {
                var k = keys[i];
                Interlocked.Exchange(ref tree, tree.AddOrUpdate(k, ignored));
            }

            Interlocked.Exchange(ref tree, tree.AddOrUpdate(key, value));

            treeTime.Stop();
            GC.KeepAlive(ignored);
            GC.Collect();
            return(treeTime.ElapsedMilliseconds);
        }
        public HashTrie <V> AddOrUpdate(int hash, V value, UpdateMethod <V> updateValue = null)
        {
            var index      = hash & LEVEL_MASK; // index from 0 to 31
            var restOfHash = hash >> LEVEL_BITS;

            if (_indexBitmap == 0)
            {
                return(new HashTrie <V>(1u << index, restOfHash == 0 ? (object)value : Empty.AddOrUpdate(restOfHash, value)));
            }

            var nodeCount = _nodes.Length;

            var pastIndexBitmap = _indexBitmap >> index;

            if ((pastIndexBitmap & 1) == 0) // no nodes at the index, could be inserted.
            {
                var subnode = restOfHash == 0 ? (object)value : Empty.AddOrUpdate(restOfHash, value);

                var pastIndexCount = pastIndexBitmap == 0 ? 0 : GetSetBitsCount(pastIndexBitmap);
                var insertIndex    = nodeCount - pastIndexCount;

                var nodesToInsert = new object[nodeCount + 1];
                if (insertIndex != 0)
                {
                    Array.Copy(_nodes, 0, nodesToInsert, 0, insertIndex);
                }
                nodesToInsert[insertIndex] = subnode;
                if (pastIndexCount != 0)
                {
                    Array.Copy(_nodes, insertIndex, nodesToInsert, insertIndex + 1, pastIndexCount);
                }

                return(new HashTrie <V>(_indexBitmap | (1u << index), nodesToInsert));
            }

            var updateIndex = nodeCount == 1 ? 0
                : nodeCount - (pastIndexBitmap == 1 ? 1 : GetSetBitsCount(pastIndexBitmap));

            var updatedNode = _nodes[updateIndex];

            if (updatedNode is HashTrie <V> )
            {
                updatedNode = ((HashTrie <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 HashTrie <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);
            }

            var nodesToUpdate = new object[nodeCount];

            if (nodesToUpdate.Length > 1)
            {
                Array.Copy(_nodes, 0, nodesToUpdate, 0, nodesToUpdate.Length);
            }
            nodesToUpdate[updateIndex] = updatedNode;

            return(new HashTrie <V>(_indexBitmap, nodesToUpdate));
        }