public MemoryPoolIterator BeginWrite(int minimumSize = 0) { MemoryPoolBlock block = null; if (_tail != null) { int remaining = _tail.Data.Offset + _tail.Data.Count - _tail.End; if (minimumSize <= remaining && remaining > 0) { block = _tail; } } if (block == null) { block = _memory.Lease(); } lock (_sync) { if (_head == null) { _head = block; } else if (block != _tail) { Volatile.Write(ref _tail.Next, block); _tail = block; } return(new MemoryPoolIterator(block, block.End)); } }
public void Ensure(int count) { if (_tail == null) { _tail = new MemoryBlockSegment(_pool.Lease()); _tailIndex = _tail.End; _head = _tail; _headIndex = _tail.Start; } Debug.Assert(_tail.Block != null); Debug.Assert(_tail.Next == null); Debug.Assert(_tail.End == _tailIndex); var segment = _tail; var block = _tail.Block; var blockIndex = _tailIndex; var remaining = count; var bytesLeftInBlock = block.Data.Offset + block.Data.Count - blockIndex; // If inadequate bytes left or if the segment is readonly if (bytesLeftInBlock < count || segment.ReadOnly) { var nextBlock = _pool.Lease(); var nextSegment = new MemoryBlockSegment(nextBlock); segment.End = blockIndex; Volatile.Write(ref segment.Next, nextSegment); segment = nextSegment; block = nextBlock; blockIndex = block.Data.Offset; segment.End = blockIndex; segment.Block = block; _tail = segment; _tailIndex = blockIndex; } }
public WritableBuffer Alloc(int minimumSize = 0) { if (Interlocked.CompareExchange(ref _producingState, 1, 0) != 0) { throw new InvalidOperationException("Already producing."); } MemoryBlockSegment segment = null; if (_tail != null && !_tail.ReadOnly) { // Try to return the tail so the calling code can append to it int remaining = _tail.Block.Data.Offset + _tail.Block.Data.Count - _tail.End; if (minimumSize <= remaining) { segment = _tail; } } if (segment == null && minimumSize > 0) { // We're out of tail space so lease a new segment only if the requested size > 0 segment = new MemoryBlockSegment(_pool.Lease()); } lock (_sync) { if (_head == null) { _head = segment; } else if (segment != null && segment != _tail) { // Append the segment to the tail if it's non-null Volatile.Write(ref _tail.Next, segment); _tail = segment; } return(new WritableBuffer(this, _pool, segment)); } }