Пример #1
0
        /// <summary>
        /// Find item in segment.
        /// </summary>
        /// <param name="key">Reference to the search key to use.</param>
        /// <param name="item">Out reference to store the found item in.</param>
        /// <param name="traits">Object that tells this segment how to treat items and keys.</param>
        /// <returns>True if an item could be found, otherwise false.</returns>
        public bool FindItem(ref TSearch key, out TStored item, ConcurrentHashtable <TStored, TSearch> traits)
        {
            var searchHash = traits.GetKeyHashCode(ref key);
            var mask       = (UInt32)(_List.Length - 1);
            var i          = searchHash & mask;

            if (!traits.IsEmpty(ref _List[i]))
            {
                var firstHash      = traits.GetItemHashCode(ref _List[i]);
                var storedItemHash = firstHash;
                var searchHashDiff = (searchHash - firstHash) & mask;

                do
                {
                    if (storedItemHash == searchHash && traits.ItemEqualsKey(ref _List[i], ref key))
                    {
                        item = _List[i];
                        return(true);
                    }

                    i = (i + 1) & mask;

                    if (traits.IsEmpty(ref _List[i]))
                    {
                        break;
                    }

                    storedItemHash = traits.GetItemHashCode(ref _List[i]);
                }while (((storedItemHash - firstHash) & mask) <= searchHashDiff);
            }

            item = default(TStored);
            return(false);
        }
Пример #2
0
        /// <summary>
        /// Inserts an item in the segment, possibly replacing an equal existing item.
        /// </summary>
        /// <param name="key">A reference to the item to insert.</param>
        /// <param name="item">An out reference where any replaced item will be written to, if no item was replaced the new item will be written to this reference.</param>
        /// <param name="traits">Object that tells this segment how to treat items and keys.</param>
        /// <returns>True if an existing item could be found and is replaced, otherwise false.</returns>
        public bool InsertItem(ref TStored key, out TStored item, ConcurrentHashtable <TStored, TSearch> traits)
        {
            var searchHash = traits.GetItemHashCode(ref key);
            var mask       = (UInt32)(_List.Length - 1);
            var i          = searchHash & mask;

            if (!traits.IsEmpty(ref _List[i]))
            {
                var firstHash      = traits.GetItemHashCode(ref _List[i]);
                var storedItemHash = firstHash;
                var searchHashDiff = (searchHash - firstHash) & mask;

                while (true)
                {
                    if (storedItemHash == searchHash && traits.ItemEqualsItem(ref _List[i], ref key))
                    {
                        item     = _List[i];
                        _List[i] = key;
                        return(true);
                    }

                    i = (i + 1) & mask;

                    if (traits.IsEmpty(ref _List[i]))
                    {
                        break;
                    }

                    storedItemHash = traits.GetItemHashCode(ref _List[i]);

                    if (((storedItemHash - firstHash) & mask) > searchHashDiff)
                    {
                        //insert
                        InsertItemAtIndex(mask, i, key, traits);
                        IncrementCount(traits);
                        item = key;
                        return(false);
                    }
                }
            }

            item = _List[i] = key;
            IncrementCount(traits);
            return(false);
        }
Пример #3
0
        /// <summary>
        /// Iterate over items in the segment.
        /// </summary>
        /// <param name="beyond">Position beyond which the next filled slot will be found and the item in that slot returned. (Starting with -1)</param>
        /// <param name="item">Out reference where the next item will be stored or default if the end of the segment is reached.</param>
        /// <param name="traits">Object that tells this segment how to treat items and keys.</param>
        /// <returns>The index position the next item has been found or -1 otherwise.</returns>
        public int GetNextItem(int beyond, out TStored item, ConcurrentHashtable <TStored, TSearch> traits)
        {
            for (int end = _List.Length; ++beyond < end;)
            {
                if (!traits.IsEmpty(ref _List[beyond]))
                {
                    item = _List[beyond];
                    return(beyond);
                }
            }

            item = default(TStored);
            return(-1);
        }
Пример #4
0
        /// <summary>
        /// Inserts an item into a *not empty* spot given by position i. It moves items forward until an empty spot is found.
        /// </summary>
        /// <param name="mask"></param>
        /// <param name="i"></param>
        /// <param name="itemCopy"></param>
        /// <param name="traits"></param>
        private void InsertItemAtIndex(UInt32 mask, UInt32 i, TStored itemCopy, ConcurrentHashtable <TStored, TSearch> traits)
        {
            do
            {
                //swap
                TStored temp = _List[i];
                _List[i] = itemCopy;
                itemCopy = temp;

                i = (i + 1) & mask;
            }while (!traits.IsEmpty(ref _List[i]));

            _List[i] = itemCopy;
        }
Пример #5
0
        protected void RemoveAtIndex(UInt32 index, ConcurrentHashtable <TStored, TSearch> traits)
        {
            var mask = (UInt32)(_List.Length - 1);
            var i    = index;
            var j    = (index + 1) & mask;

            while (!traits.IsEmpty(ref _List[j]) && (traits.GetItemHashCode(ref _List[j]) & mask) != j)
            {
                _List[i] = _List[j];

                i = j;
                j = (j + 1) & mask;
            }

            _List[i] = default(TStored);
        }
Пример #6
0
        protected virtual void ResizeList(ConcurrentHashtable <TStored, TSearch> traits)
        {
            var oldList       = _List;
            var oldListLength = oldList.Length;

            var newListLength = 2;

            while (newListLength < _Count)
            {
                newListLength <<= 1;
            }

            newListLength <<= 1;

            if (newListLength != oldListLength)
            {
                _List = new TStored[newListLength];

                var mask = (UInt32)(newListLength - 1);

                for (int i = 0; i != oldListLength; ++i)
                {
                    if (!traits.IsEmpty(ref oldList[i]))
                    {
                        var searchHash = traits.GetItemHashCode(ref oldList[i]);

                        //j is prefered insertion pos in new list.
                        var j = searchHash & mask;

                        if (traits.IsEmpty(ref _List[j]))
                        {
                            _List[j] = oldList[i];
                        }
                        else
                        {
                            var firstHash      = traits.GetItemHashCode(ref _List[j]);
                            var storedItemHash = firstHash;
                            var searchHashDiff = (searchHash - firstHash) & mask;

                            while (true)
                            {
                                j = (j + 1) & mask;

                                if (traits.IsEmpty(ref _List[j]))
                                {
                                    _List[j] = oldList[i];
                                    break;
                                }

                                storedItemHash = traits.GetItemHashCode(ref _List[j]);

                                if (((storedItemHash - firstHash) & mask) > searchHashDiff)
                                {
                                    InsertItemAtIndex(mask, j, oldList[i], traits);
                                    break;
                                }
                            }
                        }
                    }
                }

                traits.EffectTotalAllocatedSpace(newListLength - oldListLength);
            }
        }