示例#1
0
 public void Dispose()
 {
     if (StringPointer != null)
     {
         Debug.Assert(FirstFreeChunk == null);
         if (FirstFreeChunk != null)
         {
             throw new InvalidOperationException();
         }
         if (Prev != null)
         {
             Prev.Next = Next;
         }
         if (Next != null)
         {
             Next.Prev = Prev;
         }
         else
         {
             Last = Prev;
         }
         StringPointer = null;
         StringHandle.Free();
     }
 }
示例#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
 public FreeChunk(PoolSegment segment, int index, int size) {
     Debug.Assert(segment.FirstFreeChunk == null && index >= 0 && size > 0 && index + size <= segment.Size);
     Segment = segment;
     Index = index;
     Size = size;
     segment.FirstFreeChunk = this;
     InsertIntoSizeList();
 }
示例#4
0
 public FreeChunk(PoolSegment segment, int index, int size)
 {
     Debug.Assert(segment.FirstFreeChunk == null && index >= 0 && size > 0 && index + size <= segment.Size);
     Segment = segment;
     Index   = index;
     Size    = size;
     segment.FirstFreeChunk = this;
     InsertIntoSizeList();
 }
示例#5
0
 public PoolSegment(int size, int firstBufferSize)
 {
     Debug.Assert(firstBufferSize > 0 && firstBufferSize <= size && (size <= MaxSegmentSize || firstBufferSize == size));
     // + 1, so that no chunk can span the full string, which helps avoiding accidentally passing a reference to the internal buffer string to the "outside world"
     String        = new String('\u0000', size + 1);
     Size          = size;
     StringHandle  = GCHandle.Alloc(String, GCHandleType.Pinned);
     StringPointer = (char *)StringHandle.AddrOfPinnedObject();
     if (Last != null)
     {
         Last.Next = this;
         Prev      = Last;
     }
     Last = this;
     if (firstBufferSize < size)
     {
         new FreeChunk(this, firstBufferSize, size - firstBufferSize); // inserts itself into the lists
     }
 }
示例#6
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();
 }
示例#7
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));
            }
        }
示例#8
0
 private StringBuffer(PoolSegment segment, int index, int length)
 {
     Segment = segment;
     Index   = index;
     Length  = length;
 }
示例#9
0
 private StringBuffer(PoolSegment segment, int index, int length) {
     Segment = segment;
     Index = index;
     Length = length;
 }
示例#10
0
 public void Dispose() {
     if (StringPointer != null) {
         Debug.Assert(FirstFreeChunk == null);
         if (FirstFreeChunk != null) throw new InvalidOperationException();
         if (Prev != null) Prev.Next = Next;
         if (Next != null) Next.Prev = Prev;
         else Last = Prev;
         StringPointer = null;
         StringHandle.Free();
     }
 }
示例#11
0
 public PoolSegment(int size, int firstBufferSize) {
     Debug.Assert(firstBufferSize > 0 &&  firstBufferSize <= size && (size <= MaxSegmentSize || firstBufferSize == size));
     // + 1, so that no chunk can span the full string, which helps avoiding accidentally passing a reference to the internal buffer string to the "outside world"
     String = new String('\u0000', size + 1);
     Size = size;
     StringHandle = GCHandle.Alloc(String, GCHandleType.Pinned);
     StringPointer = (char*)StringHandle.AddrOfPinnedObject();
     if (Last != null) {
         Last.Next = this;
         Prev = Last;
     }
     Last = this;
     if (firstBufferSize < size)
         new FreeChunk(this, firstBufferSize, size - firstBufferSize); // inserts itself into the lists
 }