示例#1
0
            public void MoveAfterSizeHasIncreased()
            {
                Debug.Assert(Size > NextInSize.Size);
                var next = NextInSize;
                var prev = PrevInSize;

                if (prev != null)
                {
                    prev.NextInSize = next;
                }
                else
                {
                    Smallest = next;
                }
                next.PrevInSize = prev;
                prev            = next;
                next            = next.NextInSize;
                while (next != null && next.Size < Size)
                {
                    prev = next;
                    next = next.NextInSize;
                }
                PrevInSize      = prev;
                prev.NextInSize = this;
                NextInSize      = next;
                if (next != null)
                {
                    next.PrevInSize = this;
                }
                else
                {
                    Largest = this;
                }
            }
示例#2
0
 public FreeChunk(PoolSegment segment, FreeChunk prevInSegment, FreeChunk nextInSegment, int index, int size)
 {
     Debug.Assert(index >= 0 && size > 0 && index + size <= segment.Size);
     Segment       = segment;
     Index         = index;
     Size          = size;
     PrevInSegment = prevInSegment;
     NextInSegment = nextInSegment;
     if (prevInSegment != null)
     {
         Debug.Assert(prevInSegment.Index + prevInSegment.Size < index);
         prevInSegment.NextInSegment = this;
     }
     else
     {
         Debug.Assert(segment.FirstFreeChunk == nextInSegment);
         segment.FirstFreeChunk = this;
     }
     if (nextInSegment != null)
     {
         Debug.Assert(index + size < nextInSegment.Index);
         nextInSegment.PrevInSegment = this;
     }
     InsertIntoSizeList();
 }
示例#3
0
            // the following two methods are dual to each other,
            // i.e. one can be transformed into the other by way of simple search & replace
            public void MoveAfterSizeHasDecreased()
            {
                Debug.Assert(Size < PrevInSize.Size);
                var prev = PrevInSize;
                var next = NextInSize;

                if (next != null)
                {
                    next.PrevInSize = prev;
                }
                else
                {
                    Largest = prev;
                }
                prev.NextInSize = next;
                next            = prev;
                prev            = prev.PrevInSize;
                while (prev != null && prev.Size > Size)
                {
                    next = prev;
                    prev = prev.PrevInSize;
                }
                NextInSize      = next;
                next.PrevInSize = this;
                PrevInSize      = prev;
                if (prev != null)
                {
                    prev.NextInSize = this;
                }
                else
                {
                    Smallest = this;
                }
            }
示例#4
0
 public FreeChunk(PoolSegment segment, FreeChunk prevInSegment, FreeChunk nextInSegment, int index, int size) {
     Debug.Assert(index >= 0 && size > 0 && index + size <= segment.Size);
     Segment = segment;
     Index = index;
     Size = size;
     PrevInSegment = prevInSegment;
     NextInSegment = nextInSegment;
     if (prevInSegment != null) {
         Debug.Assert(prevInSegment.Index + prevInSegment.Size < index);
         prevInSegment.NextInSegment = this;
     } else {
         Debug.Assert(segment.FirstFreeChunk == nextInSegment);
         segment.FirstFreeChunk = this;
     }
     if (nextInSegment != null) {
         Debug.Assert(index + size < nextInSegment.Index);
         nextInSegment.PrevInSegment = this;
     }
     InsertIntoSizeList();
 }
示例#5
0
 private void InsertIntoSizeList() {
     var largest = FreeChunk.Largest;
     if (largest != null) {
         if (largest.Size <= Size) {
             largest.NextInSize = this;
             PrevInSize = largest;
             FreeChunk.Largest = this;
         } else {
             NextInSize = largest;
             var prev = largest.PrevInSize;
             largest.PrevInSize = this;
             if (prev != null) {
                 PrevInSize = prev;
                 prev.NextInSize = this;
                 if (Size < prev.Size) MoveAfterSizeHasDecreased();
             } else FreeChunk.Smallest = this;
         }
     } else {
         FreeChunk.Smallest = this;
         FreeChunk.Largest = this;
     }
 }
示例#6
0
            private void InsertIntoSizeList()
            {
                var largest = FreeChunk.Largest;

                if (largest != null)
                {
                    if (largest.Size <= Size)
                    {
                        largest.NextInSize = this;
                        PrevInSize         = largest;
                        FreeChunk.Largest  = this;
                    }
                    else
                    {
                        NextInSize = largest;
                        var prev = largest.PrevInSize;
                        largest.PrevInSize = this;
                        if (prev != null)
                        {
                            PrevInSize      = prev;
                            prev.NextInSize = this;
                            if (Size < prev.Size)
                            {
                                MoveAfterSizeHasDecreased();
                            }
                        }
                        else
                        {
                            FreeChunk.Smallest = this;
                        }
                    }
                }
                else
                {
                    FreeChunk.Smallest = this;
                    FreeChunk.Largest  = this;
                }
            }
示例#7
0
            public void Remove()
            {
                var prev = PrevInSegment;
                var next = NextInSegment;

                if (prev != null)
                {
                    prev.NextInSegment = next;
                }
                else
                {
                    Segment.FirstFreeChunk = next;
                }
                if (next != null)
                {
                    next.PrevInSegment = prev;
                }

                prev = PrevInSize;
                next = NextInSize;
                if (prev != null)
                {
                    prev.NextInSize = next;
                }
                else
                {
                    Smallest = next;
                }
                if (next != null)
                {
                    next.PrevInSize = prev;
                }
                else
                {
                    Largest = prev;
                }
            }
示例#8
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();
                    }
                }
            }
        }
示例#9
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));
            }
        }
示例#10
0
 public void MoveAfterSizeHasIncreased() {
     Debug.Assert(Size > NextInSize.Size);
     var next = NextInSize;
     var prev = PrevInSize;
     if (prev != null) prev.NextInSize = next;
     else Smallest = next;
     next.PrevInSize = prev;
     prev = next;
     next = next.NextInSize;
     while (next != null && next.Size < Size) {
         prev = next;
         next = next.NextInSize;
     }
     PrevInSize = prev;
     prev.NextInSize = this;
     NextInSize = next;
     if (next != null) next.PrevInSize = this;
     else Largest = this;
 }
示例#11
0
 // the following two methods are dual to each other,
 // i.e. one can be transformed into the other by way of simple search & replace
 public void MoveAfterSizeHasDecreased() {
     Debug.Assert(Size < PrevInSize.Size);
     var prev = PrevInSize;
     var next = NextInSize;
     if (next != null) next.PrevInSize = prev;
     else Largest = prev;
     prev.NextInSize = next;
     next = prev;
     prev = prev.PrevInSize;
     while (prev != null && prev.Size > Size) {
         next = prev;
         prev = prev.PrevInSize;
     }
     NextInSize = next;
     next.PrevInSize = this;
     PrevInSize = prev;
     if (prev != null) prev.NextInSize = this;
     else Smallest = this;
 }
示例#12
0
        public void Remove() {
            var prev = PrevInSegment;
            var next = NextInSegment;
            if (prev != null) prev.NextInSegment = next;
            else Segment.FirstFreeChunk = next;
            if (next != null) next.PrevInSegment = prev;

            prev = PrevInSize;
            next = NextInSize;
            if (prev != null) prev.NextInSize = next;
            else Smallest = next;
            if (next != null) next.PrevInSize = prev;
            else Largest = prev;
        }