Exemplo n.º 1
0
        private static void GrowTable <VALUE>(Table <VALUE> oldTable, Monitor monitor, HashFunction hashFunction, ResizeMonitor <VALUE> resizeMonitor)
        {
            Debug.Assert(monitor.TableGrowing(oldTable.Capacity(), oldTable.Size()));
            Table <VALUE> newTable = oldTable.Grow();

            // Install the new table before populating it with the old data, in case we find it needs to grow even more
            // while we are populating it. If that happens, we want to end up with the table installed by the final grow.
            resizeMonitor.TableGrew(newTable);
            long nullKey = oldTable.NullKey();

            // place all entries in the new table
            int capacity = oldTable.Capacity();

            for (int i = 0; i < capacity; i++)
            {
                long key = oldTable.Key(i);
                if (key != nullKey)
                {
                    // Always use the table from the resize monitor, because any put can cause a grow.
                    Table <VALUE> table     = resizeMonitor.LastTable;
                    VALUE         putResult = Put(table, monitor, hashFunction, key, oldTable.Value(i), resizeMonitor);
                    if (putResult != default(VALUE))
                    {
                        // If we somehow fail to populate the new table, reinstall the old one.
                        resizeMonitor.TableGrew(oldTable);
                        newTable.Close();
                        throw new System.InvalidOperationException("Couldn't add " + key + " when growing table");
                    }
                }
            }
            Debug.Assert(monitor.TableGrew(oldTable.Capacity(), newTable.Capacity(), newTable.Size()));
            oldTable.Close();
        }
Exemplo n.º 2
0
        public static VALUE Put <VALUE>(Table <VALUE> table, Monitor monitor, HashFunction hashFunction, long key, VALUE value, ResizeMonitor <VALUE> resizeMonitor)
        {
            long nullKey = table.NullKey();

            Debug.Assert(key != nullKey);
            int  tableMask  = table.Mask();
            int  index      = IndexOf(hashFunction, key, tableMask);
            long keyAtIndex = table.Key(index);

            if (keyAtIndex == nullKey)
            {               // this index is free, just place it there
                table.Put(index, key, value);
                Debug.Assert(monitor.PlacedAtFreeAndIntendedIndex(key, index));
                return(default(VALUE));
            }
            else if (keyAtIndex == key)
            {               // this index is occupied, but actually with the same key
                return(table.PutValue(index, value));
            }
            else
            {               // look at the neighbors of this entry to see if any is the requested key
                long hopBits = table.HopBits(index);
                while (hopBits > 0)
                {
                    int hopIndex = NextIndex(index, numberOfTrailingZeros(hopBits) + 1, tableMask);
                    if (table.Key(hopIndex) == key)
                    {
                        return(table.PutValue(hopIndex, value));
                    }
                    hopBits &= hopBits - 1;
                }
            }

            // this key does not exist in this set. put it there using hop-scotching
            if (HopScotchPut(table, monitor, hashFunction, key, value, index, tableMask, nullKey))
            {               // we managed to wiggle our way to a free spot and put it there
                return(default(VALUE));
            }

            // we couldn't add this value, even in the H-1 neighborhood, so grow table...
            GrowTable(table, monitor, hashFunction, resizeMonitor);
            Table <VALUE> resizedTable = resizeMonitor.LastTable;

            // ...and try again
            return(Put(resizedTable, monitor, hashFunction, key, value, resizeMonitor));
        }