public static int Seek(ReadCursor begin, ReadCursor end, out ReadCursor result, byte byte0) { var enumerator = new SegmentEnumerator(begin, end); while (enumerator.MoveNext()) { var segmentPart = enumerator.Current; var segment = segmentPart.Segment; var span = segment.Buffer.Span.Slice(segmentPart.Start, segmentPart.Length); int index = span.IndexOf(byte0); if (index != -1) { result = new ReadCursor(segment, segmentPart.Start + index); return(span[index]); } } result = end; return(-1); }
private void GetResult(ref ReadResult result) { if (_writerCompletion.IsCompletedOrThrow()) { result.ResultFlags |= ResultFlags.Completed; } var isCancelled = _readerAwaitable.ObserveCancelation(); if (isCancelled) { result.ResultFlags |= ResultFlags.Cancelled; } // No need to read end if there is no head var head = _readHead; if (head != null) { // Reading commit head shared with writer result.ResultBuffer.BufferEnd.Segment = _commitHead; result.ResultBuffer.BufferEnd.Index = _commitHeadIndex; result.ResultBuffer.BufferLength = ReadCursor.GetLength(head, head.Start, _commitHead, _commitHeadIndex); result.ResultBuffer.BufferStart.Segment = head; result.ResultBuffer.BufferStart.Index = head.Start; } if (isCancelled) { _readingState.BeginTentative(ExceptionResource.AlreadyReading); } else { _readingState.Begin(ExceptionResource.AlreadyReading); } }
// Reading void IPipeReader.Advance(ReadCursor consumed, ReadCursor examined) { BufferSegment returnStart = null; BufferSegment returnEnd = null; // Reading commit head shared with writer Action continuation = null; lock (_sync) { var examinedEverything = examined.Segment == _commitHead && examined.Index == _commitHeadIndex; if (!consumed.IsDefault) { if (_readHead == null) { PipelinesThrowHelper.ThrowInvalidOperationException(ExceptionResource.AdvanceToInvalidCursor); return; } returnStart = _readHead; returnEnd = consumed.Segment; // Check if we crossed _maximumSizeLow and complete backpressure var consumedBytes = ReadCursor.GetLength(returnStart, returnStart.Start, consumed.Segment, consumed.Index); var oldLength = _length; _length -= consumedBytes; if (oldLength >= _maximumSizeLow && _length < _maximumSizeLow) { continuation = _writerAwaitable.Complete(); } // Check if we consumed entire last segment // if we are going to return commit head // we need to check that there is no writing operation that // might be using tailspace if (consumed.Index == returnEnd.End && !(_commitHead == returnEnd && _writingState.IsActive)) { var nextBlock = returnEnd.Next; if (_commitHead == returnEnd) { _commitHead = nextBlock; _commitHeadIndex = nextBlock?.Start ?? 0; } _readHead = nextBlock; returnEnd = nextBlock; } else { _readHead = consumed.Segment; _readHead.Start = consumed.Index; } } // We reset the awaitable to not completed if we've examined everything the producer produced so far // but only if writer is not completed yet if (examinedEverything && !_writerCompletion.IsCompleted) { // Prevent deadlock where reader awaits new data and writer await backpressure if (!_writerAwaitable.IsCompleted) { PipelinesThrowHelper.ThrowInvalidOperationException(ExceptionResource.BackpressureDeadlock); } _readerAwaitable.Reset(); } _readingState.End(ExceptionResource.NoReadToComplete); } while (returnStart != null && returnStart != returnEnd) { returnStart.Dispose(); returnStart = returnStart.Next; } TrySchedule(_writerScheduler, continuation); }
public static void Advance(this IPipeReader input, ReadCursor cursor) { input.Advance(cursor, cursor); }
internal ReadableBuffer(ReadCursor start, ReadCursor end) { BufferStart = start; BufferEnd = end; BufferLength = start.GetLength(end); }
internal void ClearCursors() { BufferStart = default(ReadCursor); BufferEnd = default(ReadCursor); }
/// <summary> /// Forms a slice out of the given <see cref="ReadableBuffer"/>, beginning at 'start', ending at the existing <see cref="ReadableBuffer"/>'s end. /// </summary> /// <param name="start">The starting (inclusive) <see cref="ReadCursor"/> at which to begin this slice.</param> public ReadableBuffer Slice(ReadCursor start) { BufferEnd.BoundsCheck(start); return(new ReadableBuffer(start, BufferEnd)); }
/// <summary> /// /// </summary> public BufferEnumerator(ReadCursor start, ReadCursor end) { _segmentEnumerator = new SegmentEnumerator(start, end); _current = default(Buffer <byte>); }