private void AllocateMemory(int sizeHint) { if (_head == null) { // We need to allocate memory to write since nobody has written before BufferSegment newSegment = AllocateSegment(sizeHint); // Set all the pointers _head = _tail = newSegment; _tailBytesBuffered = 0; } else { int bytesLeftInBuffer = _tailMemory.Length; if (bytesLeftInBuffer == 0 || bytesLeftInBuffer < sizeHint) { if (_tailBytesBuffered > 0) { // Flush buffered data to the segment _tail.End += _tailBytesBuffered; _tailBytesBuffered = 0; } BufferSegment newSegment = AllocateSegment(sizeHint); _tail.SetNext(newSegment); _tail = newSegment; } } }
private void AllocateWriteHeadUnsynchronized(int sizeHint) { _operationState.BeginWrite(); if (_writingHead == null) { // We need to allocate memory to write since nobody has written before BufferSegment newSegment = CreateSegmentUnsynchronized(); newSegment.SetMemory(_pool.Rent(GetSegmentSize(sizeHint))); // Set all the pointers _writingHead = _readHead = _readTail = newSegment; } else { int bytesLeftInBuffer = _writingHead.WritableBytes; if (bytesLeftInBuffer == 0 || bytesLeftInBuffer < sizeHint) { BufferSegment newSegment = CreateSegmentUnsynchronized(); newSegment.SetMemory(_pool.Rent(GetSegmentSize(sizeHint))); _writingHead.SetNext(newSegment); _writingHead = newSegment; } } }
internal Memory <byte> GetMemory(int minimumSize) { if (_writerCompletion.IsCompleted) { ThrowHelper.ThrowInvalidOperationException_NoWritingAllowed(); } if (minimumSize < 0) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.minimumSize); } lock (_sync) { BufferSegment segment = _writingHead ?? AllocateWriteHeadUnsynchronized(minimumSize); int bytesLeftInBuffer = segment.WritableBytes; // If inadequate bytes left or if the segment is readonly if (bytesLeftInBuffer == 0 || bytesLeftInBuffer < minimumSize || segment.ReadOnly) { BufferSegment nextSegment = CreateSegmentUnsynchronized(); nextSegment.SetMemory(_pool.Rent(Math.Max(_minimumSegmentSize, minimumSize))); segment.SetNext(nextSegment); _writingHead = nextSegment; } } return(_writingHead.AvailableMemory.Slice(_writingHead.End, _writingHead.WritableBytes)); }
private void AllocateWriteHeadSynchronized(int sizeHint) { lock (_sync) { _operationState.BeginWrite(); if (_writingHead == null) { // We need to allocate memory to write since nobody has written before BufferSegment newSegment = AllocateSegment(sizeHint); // Set all the pointers _writingHead = _readHead = _readTail = _lastExamined = newSegment; } else { int bytesLeftInBuffer = _writingMemory.Length; if (bytesLeftInBuffer == 0 || bytesLeftInBuffer < sizeHint) { if (_buffered > 0) { // Flush buffered data to the segment _writingHead.End += _buffered; _buffered = 0; } BufferSegment newSegment = AllocateSegment(sizeHint); _writingHead.SetNext(newSegment); _writingHead = newSegment; } } } }
private void AllocateWriteHeadUnsynchronized(int sizeHint) { BufferSegment segment = null; if (_writingHead != null) { segment = _writingHead; int bytesLeftInBuffer = segment.WritableBytes; // If inadequate bytes left or if the segment is readonly if (bytesLeftInBuffer == 0 || bytesLeftInBuffer < sizeHint || segment.ReadOnly) { BufferSegment nextSegment = CreateSegmentUnsynchronized(); nextSegment.SetMemory(_pool.Rent(GetSegmentSize(sizeHint))); segment.SetNext(nextSegment); _writingHead = nextSegment; } } else { if (_commitHead != null && !_commitHead.ReadOnly) { // Try to return the tail so the calling code can append to it int remaining = _commitHead.WritableBytes; if (sizeHint <= remaining && remaining > 0) { // Free tail space of the right amount, use that segment = _commitHead; // Set write head to assigned segment _writingHead = segment; return; } } // No free tail space, allocate a new segment segment = CreateSegmentUnsynchronized(); segment.SetMemory(_pool.Rent(GetSegmentSize(sizeHint))); if (_commitHead == null) { // No previous writes have occurred _commitHead = segment; } else if (segment != _commitHead && _commitHead.Next == null) { // Append the segment to the commit head if writes have been committed // and it isn't the same segment (unused tail space) _commitHead.SetNext(segment); } // Set write head to assigned segment _writingHead = segment; } }
private void CreateNewTailSegment() { var nextSegment = CreateBufferSegment(); nextSegment.SetMemory(_pool.Rent(GetSegmentSize())); _readTail.SetNext(nextSegment); _readTail = nextSegment; }
private BufferSegment AllocateWriteHeadUnsynchronized(int count) { BufferSegment segment = null; if (_commitHead != null && !_commitHead.ReadOnly) { // Try to return the tail so the calling code can append to it int remaining = _commitHead.WritableBytes; if (count <= remaining) { // Free tail space of the right amount, use that segment = _commitHead; } } if (segment == null) { // No free tail space, allocate a new segment segment = CreateSegmentUnsynchronized(); segment.SetMemory(_pool.Rent(count)); } if (_commitHead == null) { // No previous writes have occurred _commitHead = segment; } else if (segment != _commitHead && _commitHead.Next == null) { // Append the segment to the commit head if writes have been committed // and it isn't the same segment (unused tail space) _commitHead.SetNext(segment); } // Set write head to assigned segment _writingHead = segment; return(segment); }
internal void Append(ReadableBuffer buffer) { if (buffer.IsEmpty) { return; // nothing to do } EnsureAlloc(); BufferSegment clonedEnd; var clonedBegin = BufferSegment.Clone(buffer.Start, buffer.End, out clonedEnd); if (_writingHead == null) { // No active write lock (_sync) { if (_commitHead == null) { // No allocated buffers yet, not locking as _readHead will be null _commitHead = clonedBegin; } else { Debug.Assert(_commitHead.Next == null); // Allocated buffer, append as next segment _commitHead.SetNext(clonedBegin); } } } else { Debug.Assert(_writingHead.Next == null); // Active write, append as next segment _writingHead.SetNext(clonedBegin); } // Move write head to end of buffer _writingHead = clonedEnd; _currentWriteLength += buffer.Length; }
internal Memory <byte> GetMemory(int sizeHint) { if (_writerCompletion.IsCompleted) { ThrowHelper.ThrowInvalidOperationException_NoWritingAllowed(); } if (sizeHint < 0) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.minimumSize); } lock (_sync) { BufferSegment segment = _writingHead ?? AllocateWriteHeadUnsynchronized(sizeHint); int bytesLeftInBuffer = segment.WritableBytes; // If inadequate bytes left or if the segment is readonly if (bytesLeftInBuffer == 0 || bytesLeftInBuffer < sizeHint || segment.ReadOnly) { BufferSegment nextSegment = CreateSegmentUnsynchronized(); nextSegment.SetMemory(_pool.Rent(GetSegmentSize(sizeHint))); segment.SetNext(nextSegment); _writingHead = nextSegment; } } // Slice the AvailableMemory to the WritableBytes size int end = _writingHead.End; Memory <byte> availableMemory = _writingHead.AvailableMemory; availableMemory = availableMemory.Slice(end, availableMemory.Length - end); return(availableMemory); }