예제 #1
0
        public void Dispose()
        {
            int size = Length;

            Length = -1;
            if (size > 0)
            {
                lock (SyncRoot) {
                    Allocated -= size;
                    if (size <= MaxSegmentSize)
                    {
                        FreeChunk prev = null;
                        FreeChunk next = Segment.FirstFreeChunk;
                        while (next != null && Index > next.Index)
                        {
                            prev = next;
                            next = next.NextInSegment;
                        }
                        if (prev == null || prev.Index + prev.Size != Index)
                        {
                            if (next != null && Index + size == next.Index)
                            {
                                next.Index = Index;
                                next.Size += size;
                                var nextNext = next.NextInSize;
                                if (nextNext != null && next.Size > nextNext.Size)
                                {
                                    next.MoveAfterSizeHasIncreased();
                                }
                            }
                            else
                            {
                                new FreeChunk(Segment, prev, next, Index, size); // inserts itself into the lists
                            }
                        }
                        else
                        {
                            if (next != null && Index + size == next.Index)
                            {
                                prev.Size += size + next.Size;
                                next.Remove();
                            }
                            else
                            {
                                prev.Size += size;
                            }
                            if (prev.NextInSize != null && prev.Size > prev.NextInSize.Size)
                            {
                                prev.MoveAfterSizeHasIncreased();
                            }
                        }
                        Segment.AssertIntegrity();
                        var first = Segment.FirstFreeChunk;
                        if (first.Size == Segment.Size && ++NumberOfUnusedSegments > MaxNumberOfUnusedSegments)
                        {
                            --NumberOfUnusedSegments;
                            first.Remove();
                            Segment.Dispose();
                        }
                    }
                    else // size > MaxSegmentSize
                    {
                        Debug.Assert(size == Segment.Size);
                        Segment.Dispose();
                    }
                }
            }
        }
예제 #2
0
        public static StringBuffer Create(int minLength)
        {
            int size = unchecked (minLength + (MinChunkSize - 1));

            if (size > (MinChunkSize - 1))                      // minLength > 0 && minLength <= System.Int32.MaxValue - (MinChunkSize - 1)
            {
                size -= (int)((uint)size % (uint)MinChunkSize); // round down to multiple of MinChunkSize
                lock (SyncRoot) {
                    Allocated += size;
                    FreeChunk chunk = FreeChunk.Largest;
                    if (chunk != null) // find smallest free chunk that is large enough to hold the buffer
                    {
                        if (size > 10 * MinChunkSize)
                        {
                            var prev = chunk.PrevInSize;
                            while (prev != null && prev.Size >= size)
                            {
                                chunk = prev;
                                prev  = prev.PrevInSize;
                            }
                        }
                        else
                        {
                            chunk = FreeChunk.Smallest;
                            var next = chunk.NextInSize;
                            while (chunk.Size < size && next != null)
                            {
                                chunk = next;
                                next  = next.NextInSize;
                            }
                        }
                        if (size <= chunk.Size)
                        {
                            int index = chunk.Index;
                            if (index == 0 && chunk.Size == chunk.Segment.Size)
                            {
                                --NumberOfUnusedSegments;
                            }
                            if (size != chunk.Size)
                            {
                                chunk.Index += size;
                                chunk.Size  -= size;
                                var prev = chunk.PrevInSize;
                                if (prev != null && chunk.Size < prev.Size)
                                {
                                    chunk.MoveAfterSizeHasDecreased();
                                }
                            }
                            else
                            {
                                chunk.Remove();
                            }
                            chunk.Segment.AssertIntegrity();
                            return(new StringBuffer(chunk.Segment, index, size));
                        }
                    }
                    return(PoolSegment.AllocateStringBufferInNewSegment(size));
                }
            }
            else
            {
                if (minLength < 0)
                {
                    throw new ArgumentOutOfRangeException("minLength", "minLength is negative.");
                }
                else if (minLength > 0)
                {
                    throw new ArgumentOutOfRangeException("minLength", "minLength is too large. The maximum string buffer length is approximately 2^30.");
                }
                return(new StringBuffer(null, 0, 0));
            }
        }