Esempio n. 1
0
        /// <summary>
        /// Removes all the elements that match the conditions defined by the specified predicate.
        /// </summary>
        /// <param name="match">The <see cref="System.Predicate{T}"/> delegate that defines the conditions of the elements to remove.</param>
        /// <returns>
        /// The number of elements removed from the <see cref="Partition{T}"/>.
        /// </returns>
        public long RemoveAll(Predicate <T> match)
        {
            long RemovedCount = 0;

            int SegmentCount = SegmentTable.Count;
            int SegmentIndex = 0;

            while (SegmentIndex < SegmentCount)
            {
                ISegment <T> Segment = SegmentTable[SegmentIndex];

                RemovedCount += Segment.RemoveAll(match);

                if (Segment.Count == 0)
                {
                    SegmentTable.RemoveAt(SegmentIndex);
                    SegmentTable.Add(Segment);
                    SegmentCount--;
                }
                else
                {
                    SegmentIndex++;
                }
            }

            Count -= RemovedCount;
            RebuildCache();

#if DEBUG
            AssertInvariant();
#endif

            return(RemovedCount);
        }
Esempio n. 2
0
        /// <summary>
        /// Removes the first occurrence of a specific object from the <see cref="Partition{T}"/>.
        /// </summary>
        /// <param name="item">The object to remove from the <see cref="Partition{T}"/>. The value can be null for reference types.</param>
        /// <returns>
        /// true if <paramref name="item"/> is successfully removed; otherwise, false. This method also returns false if <paramref name="item"/> was not found in the <see cref="Partition{T}"/>.
        /// </returns>
        public bool Remove(T item)
        {
            bool Result = false;

            foreach (ISegment <T> Segment in SegmentTable)
            {
                if (Segment.Remove(item))
                {
                    Result = true;
                    Count--;

                    if (Segment.Count == 0)
                    {
                        SegmentTable.Remove(Segment);
                        SegmentTable.Add(Segment);
                    }

                    break;
                }
            }

            RebuildCache();

#if DEBUG
            AssertInvariant();
#endif

            return(Result);
        }
Esempio n. 3
0
        /// <summary>
        /// Removes segments starting from the specified index in the <see cref="Partition{T}"/>.
        /// </summary>
        /// <param name="index">The zero-based index of the first segment to remove.</param>
        /// <param name="count">The number of segments to remove.</param>
        protected virtual void RemoveSegmentRange(int index, int count)
        {
            Debug.Assert(index >= 0);
            Debug.Assert(count >= 0);
            Debug.Assert(index + count <= SegmentTable.Count);

            SegmentTable.RemoveRange(index, count);
        }
Esempio n. 4
0
        /// <summary>
        /// Removes a range of elements from the <see cref="Partition{T}"/>.
        /// </summary>
        /// <param name="segmentIndex">The segment index of the position of the first element to remove.</param>
        /// <param name="elementIndex">The element index of the position of the first element to remove.</param>
        /// <param name="cacheIndex">The cache index of the position of the first element to remove.</param>
        /// <param name="count">The number of elements to remove.</param>
        public void RemoveRange(int segmentIndex, int elementIndex, int cacheIndex, long count)
        {
            Debug.Assert(IsValidPosition(segmentIndex, elementIndex, true));
            Debug.Assert(cacheIndex >= 0);

            long RemainingCount = count;

            while (RemainingCount > 0)
            {
                Debug.Assert(segmentIndex >= 0 && segmentIndex < SegmentTable.Count);
                Debug.Assert(elementIndex >= 0 && elementIndex < SegmentTable[segmentIndex].Count);

                int Removable = SegmentTable[segmentIndex].Count - elementIndex;
                if (Removable > RemainingCount)
                {
                    Removable = (int)RemainingCount;
                }

                SegmentTable[segmentIndex].RemoveRange(elementIndex, Removable);

                if (SegmentTable[segmentIndex].Count > 0)
                {
                    segmentIndex++;
                }
                else
                {
                    ISegment <T> Segment = SegmentTable[segmentIndex];
                    SegmentTable.RemoveAt(segmentIndex);
                    SegmentTable.Add(Segment);
                }

                RemainingCount -= Removable;
                elementIndex    = 0;
            }

            Debug.Assert(RemainingCount == 0);

            Count -= count;

            RebuildCacheFrom(cacheIndex);

#if DEBUG
            AssertInvariant();
#endif
        }
Esempio n. 5
0
        /// <summary>
        /// Increases the <see cref="Partition{T}"/>.Capacity by the given amount.
        /// </summary>
        /// <param name="extended">The number of elements added to the <see cref="Partition{T}"/>.Capacity.</param>
        public void ExtendCapacity(long extended)
        {
            Debug.Assert(extended >= 0);

            long RemainingCapacity = extended;

            // We first extend the capacity of the last segment in the partition.
            if (SegmentTable[SegmentTable.Count - 1].Capacity < MaxSegmentCapacity)
            {
                int Extendable = SegmentTable[SegmentTable.Count - 1].Extendable;
                if (Extendable > RemainingCapacity)
                {
                    Extendable = (int)RemainingCapacity;
                }

                int effectiveExtended;
                SegmentTable[SegmentTable.Count - 1].Extend(Extendable, out effectiveExtended);
                RemainingCapacity -= effectiveExtended;
            }

            Debug.Assert(RemainingCapacity >= 0);

            // Then we add as many empty segments as necessary to increase the partition capacity.
            while (RemainingCapacity > MaxSegmentCapacity)
            {
                SegmentTable.Add(CreateMaxCapacitySegment());
                RemainingCapacity -= MaxSegmentCapacity;
            }

            Debug.Assert(RemainingCapacity >= 0 && RemainingCapacity <= MaxSegmentCapacity);

            if (RemainingCapacity > 0)
            {
                SegmentTable.Add(CreateSegment((int)RemainingCapacity));
            }

            Capacity += extended;

            RebuildCache();

#if DEBUG
            AssertInvariant();
#endif
        }
Esempio n. 6
0
        /// <summary>
        /// Makes room for a number of elements starting at the specified position. Elements already the specified position and beyond are moved toward the end of the <see cref="Partition{T}"/>.
        /// </summary>
        /// <param name="segmentIndex">The segment index of the position at which uninitialized elements should be inserted.</param>
        /// <param name="elementIndex">The element index of the position at which uninitialized elements should be inserted.</param>
        /// <param name="cacheIndex">The cache index of the position at which uninitialized elements should be inserted.</param>
        /// <param name="count">The number of elements to insert.</param>
        public void MakeRoom(int segmentIndex, int elementIndex, int cacheIndex, long count)
        {
            Debug.Assert(IsValidPosition(segmentIndex, elementIndex, true));
            Debug.Assert(cacheIndex >= 0);
            Debug.Assert(count >= 0);

            long RemainingCount = count;
            int  effectiveExtended;

            // First we try to make room in just one segment.
            int Extendable = SegmentTable[segmentIndex].Extendable;

            if (Extendable >= RemainingCount)
            {
                SegmentTable[segmentIndex].MakeRoom(elementIndex, (int)RemainingCount, out effectiveExtended);
                Capacity += effectiveExtended;
            }
            else
            {
                // Otherwise, we're going to need to move elements upward.
                int SegmentEndCount = SegmentTable[segmentIndex].Count - elementIndex;
                int NextExtendable  = (segmentIndex + 1 < SegmentTable.Count) ? SegmentTable[segmentIndex + 1].Extendable : -1;

                Debug.Assert(SegmentEndCount >= 0);
                Debug.Assert(elementIndex + SegmentEndCount + RemainingCount > MaxSegmentCapacity);

                // If there is room for elements in the next segment, use it.
                if (SegmentEndCount <= NextExtendable)
                {
                    Debug.Assert(NextExtendable >= 0);
                    Debug.Assert(segmentIndex + 1 < SegmentTable.Count);
                    Debug.Assert(SegmentTable[segmentIndex + 1].Count + SegmentEndCount <= MaxSegmentCapacity);

                    SegmentTable[segmentIndex + 1].MakeRoom(0, SegmentEndCount, out effectiveExtended);
                    Capacity += effectiveExtended;
                }

                // Otherwise, perform a split.
                else if (SegmentEndCount > 0)
                {
                    ISegment <T> NewSegment = CreateSegment(SegmentEndCount);
                    NewSegment.MakeRoom(0, SegmentEndCount, out effectiveExtended);
                    Capacity += NewSegment.Capacity;
                    SegmentTable.Insert(segmentIndex + 1, NewSegment);
                }

                // Move the end of the current segment to the new one.
                if (SegmentEndCount > 0)
                {
                    SegmentTable[segmentIndex].MoveTo(SegmentTable[segmentIndex + 1], 0, elementIndex, SegmentEndCount);
                }

                // Check that we didn't do all this for nothing.
                Debug.Assert(elementIndex == SegmentTable[segmentIndex].Count);

                // Resume making room.
                Extendable = SegmentTable[segmentIndex].Extendable;
                if (Extendable > RemainingCount)
                {
                    Extendable = (int)RemainingCount;
                }
                SegmentTable[segmentIndex].MakeRoom(elementIndex, Extendable, out effectiveExtended);
                Capacity       += effectiveExtended;
                RemainingCount -= Extendable;

                Debug.Assert(RemainingCount >= 0);

                segmentIndex++;

                if (segmentIndex < SegmentTable.Count)
                {
                    Extendable = SegmentTable[segmentIndex].Extendable;
                    if (Extendable > RemainingCount)
                    {
                        Extendable = (int)RemainingCount;
                    }
                    SegmentTable[segmentIndex].MakeRoom(0, Extendable, out effectiveExtended);
                    Capacity       += effectiveExtended;
                    RemainingCount -= Extendable;

                    Debug.Assert(RemainingCount >= 0);
                }

                while (RemainingCount >= MaxSegmentCapacity)
                {
                    ISegment <T> NewSegment = CreateMaxCapacitySegment();
                    NewSegment.MakeRoom(0, MaxSegmentCapacity, out effectiveExtended);
                    Capacity += NewSegment.Capacity;

                    SegmentTable.Insert(segmentIndex, NewSegment);
                    RemainingCount -= MaxSegmentCapacity;

                    segmentIndex++;
                }

                if (RemainingCount > 0)
                {
                    ISegment <T> NewSegment = CreateSegment((int)RemainingCount);
                    NewSegment.MakeRoom(0, (int)RemainingCount, out effectiveExtended);
                    Capacity += NewSegment.Capacity;

                    SegmentTable.Insert(segmentIndex, NewSegment);
                }
            }

            Count += count;
            ResizeCache();

            RebuildCacheFrom(cacheIndex);

#if DEBUG
            AssertInvariant();
#endif
        }