private ReadableBuffer(ref ReadableBuffer buffer) { var begin = buffer._start; var end = buffer._end; BufferSegment segmentTail; var segmentHead = BufferSegment.Clone(begin, end, out segmentTail); begin = new ReadCursor(segmentHead); end = new ReadCursor(segmentTail, segmentTail.End); _start = begin; _end = end; _isOwner = true; _first = buffer._first; _length = buffer._length; }
public ReadableBuffer Clone() { var begin = _start; var end = _end; var segmentHead = MemoryBlockSegment.Clone(begin, end); var segmentTail = segmentHead; while (segmentTail.Next != null) { segmentTail = segmentTail.Next; } begin = new ReadCursor(segmentHead); end = new ReadCursor(segmentTail, segmentTail.End); return(new ReadableBuffer(_channel, begin, end, isOwner: true)); }
private ReadableBuffer Read() { // CompareExchange not required as its setting to current value if test fails if (Interlocked.Exchange(ref _consumingState, State.Active) != State.NotActive) { throw new InvalidOperationException("Already consuming."); } ReadCursor readEnd; // Reading commit head shared with writer lock (_sync) { readEnd = new ReadCursor(_commitHead, _commitHeadIndex); } return(new ReadableBuffer(new ReadCursor(_readHead), readEnd)); }
private ReadableBuffer(ref ReadableBuffer buffer) { var begin = buffer._start; var end = buffer._end; BufferSegment segmentTail; var segmentHead = BufferSegment.Clone(begin, end, out segmentTail); begin = new ReadCursor(segmentHead); end = new ReadCursor(segmentTail, segmentTail.End); _start = begin; _end = end; _length = buffer._length; begin.TryGetBuffer(end, out _first, out begin); }
public void AdvanceReader(ReadCursor consumed, ReadCursor examined) { BufferSegment returnStart = null; BufferSegment returnEnd = null; if (!consumed.IsDefault) { returnStart = _readHead; returnEnd = consumed.Segment; _readHead = consumed.Segment; _readHead.Start = consumed.Index; } // Reading commit head shared with writer lock (_sync) { if (!examined.IsDefault && examined.Segment == _commitHead && examined.Index == _commitHeadIndex && Reading.Status == TaskStatus.WaitingForActivation) { Interlocked.CompareExchange( ref _awaitableState, _awaitableIsNotCompleted, _awaitableIsCompleted); } } while (returnStart != returnEnd) { var returnSegment = returnStart; returnStart = returnStart.Next; returnSegment.Dispose(); } #if DEBUG _consumingLocation = null; #endif // CompareExchange not required as its setting to current value if test fails if (Interlocked.Exchange(ref _consumingState, State.NotActive) != State.Active) { ThrowHelper.ThrowInvalidOperationException(ExceptionResource.NotConsumingToComplete); } }
private ReadableBuffer(ref ReadableBuffer buffer) { _channel = buffer._channel; var begin = buffer._start; var end = buffer._end; MemoryBlockSegment segmentTail; var segmentHead = MemoryBlockSegment.Clone(begin, end, out segmentTail); begin = new ReadCursor(segmentHead); end = new ReadCursor(segmentTail, segmentTail.End); _start = begin; _end = end; _isOwner = true; _span = buffer._span; _length = buffer._length; }
public void EndRead( ReadCursor consumed, ReadCursor examined) { MemoryBlockSegment returnStart = null; MemoryBlockSegment returnEnd = null; lock (_sync) { if (!consumed.IsDefault) { returnStart = _head; returnEnd = consumed.Segment; _head = consumed.Segment; _head.Start = consumed.Index; } if (!examined.IsDefault && examined.IsEnd && Completion.Status == TaskStatus.WaitingForActivation) { Interlocked.CompareExchange( ref _awaitableState, _awaitableIsNotCompleted, _awaitableIsCompleted); } } while (returnStart != returnEnd) { var returnSegment = returnStart; returnStart = returnStart.Next; returnSegment.Dispose(); } if (Interlocked.CompareExchange(ref _consumingState, 0, 1) != 1) { throw new InvalidOperationException("No ongoing consuming operation to complete."); } }
internal void ClearCursors() { _start = default(ReadCursor); _end = default(ReadCursor); }
public void Consumed(ReadCursor consumed) { _channel.EndRead(consumed, consumed); }
/// <summary> /// Forms a slice out of the given <see cref="ReadableBuffer"/>, beginning at 'start', and is at most length bytes /// </summary> /// <param name="start">The starting (inclusive) <see cref="ReadCursor"/> at which to begin this slice.</param> /// <param name="length">The length of the slice</param> public ReadableBuffer Slice(ReadCursor start, int length) { return(Slice(start, start.Seek(length))); }
/// <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) { return(new ReadableBuffer(start, _end)); }
/// <summary> /// Searches for a byte in the <see cref="ReadableBuffer"/> and returns a sliced <see cref="ReadableBuffer"/> that /// contains all data up to and excluding the byte, and a <see cref="ReadCursor"/> that points to the byte. /// </summary> /// <param name="b1">The first byte to search for</param> /// <param name="slice">A <see cref="ReadableBuffer"/> slice that contains all data up to and excluding the first byte.</param> /// <param name="cursor">A <see cref="ReadCursor"/> that points to the second byte</param> /// <returns>True if the byte sequence was found, false if not found</returns> public bool TrySliceTo(byte b1, out ReadableBuffer slice, out ReadCursor cursor) { if (IsEmpty) { slice = default(ReadableBuffer); cursor = default(ReadCursor); return(false); } var byte0Vector = CommonVectors.GetVector(b1); var seek = 0; foreach (var memory in this) { var currentSpan = memory.Span; var found = false; if (Vector.IsHardwareAccelerated) { while (currentSpan.Length >= VectorWidth) { var data = currentSpan.Read <Vector <byte> >(); var byte0Equals = Vector.Equals(data, byte0Vector); if (byte0Equals.Equals(Vector <byte> .Zero)) { currentSpan = currentSpan.Slice(VectorWidth); seek += VectorWidth; } else { var index = FindFirstEqualByte(ref byte0Equals); seek += index; found = true; break; } } } if (!found) { // Slow search for (int i = 0; i < currentSpan.Length; i++) { if (currentSpan[i] == b1) { found = true; break; } seek++; } } if (found) { cursor = _start.Seek(seek); slice = Slice(_start, cursor); return(true); } } slice = default(ReadableBuffer); cursor = default(ReadCursor); return(false); }
/// <summary> /// Forms a slice out of the given <see cref="ReadableBuffer"/>, beginning at 'start', ending at 'end' (inclusive). /// </summary> /// <param name="start">The index at which to begin this slice.</param> /// <param name="end">The end (inclusive) of the slice</param> public ReadableBuffer Slice(int start, ReadCursor end) { return(Slice(_start.Seek(start), end)); }
internal ReadableBuffer(Channel channel, ReadCursor start, ReadCursor end) : this(channel, start, end, isOwner : false) { }
public static void Advance(this IReadableChannel input, ReadCursor cursor) { input.Advance(cursor, cursor); }
/// <summary> /// Moves forward the channels read cursor to after the consumed data. /// </summary> /// <param name="consumed">Marks the extent of the data that has been succesfully proceesed.</param> /// <param name="examined">Marks the extent of the data that has been read and examined.</param> /// <remarks> /// The memory for the consumed data will be released and no longer available. /// The examined data communicates to the channel when it should signal more data is available. /// </remarks> public void Advance(ReadCursor consumed, ReadCursor examined) => _channel.AdvanceReader(consumed, examined);
public void EndRead(ReadCursor end) { EndRead(end, end); }
public ReadableBuffer Slice(ReadCursor start, ReadCursor end) { return(new ReadableBuffer(_channel, start, end)); }
internal void EndRead(ReadCursor end) { EndRead(end, end); }
void IReadableChannel.Advance(ReadCursor consumed, ReadCursor examined) => AdvanceReader(consumed, examined);
public void Consumed(ReadCursor consumed, ReadCursor examined) { _channel.EndRead(consumed, examined); }
internal ReadableBuffer(ReadCursor start, ReadCursor end) : this(start, end, isOwner : false) { }