public void IncomingData(byte[] buffer, int offset, int count) { lock (_sync) { // Must call Add() before bytes are available to consumer, to ensure that Length is >= 0 _bufferSizeControl?.Add(count); if (count > 0) { if (_tail == null) { _tail = _memory.Lease(); } var iterator = new MemoryPoolIterator(_tail, _tail.End); iterator.CopyFrom(buffer, offset, count); if (_head == null) { _head = _tail; } _tail = iterator.Block; } else { RemoteIntakeFin = true; } Complete(); } }
private void ProducingCompleteNoPreComplete(MemoryPoolIterator end) { MemoryPoolBlock blockToReturn = null; lock (_returnLock) { // Both ProducingComplete and WriteAsync should not call this method // if _lastStart was not set. Debug.Assert(!_lastStart.IsDefault); // If the socket has been closed, return the produced blocks // instead of advancing the now non-existent tail. if (_tail != null) { _tail = end.Block; _tail.End = end.Index; } else { blockToReturn = _lastStart.Block; } _lastStart = default(MemoryPoolIterator); } if (blockToReturn != null) { ThreadPool.QueueUserWorkItem(_returnBlocks, blockToReturn); } }
public void ConsumingComplete( MemoryPoolIterator consumed, MemoryPoolIterator examined) { MemoryPoolBlock returnStart = null; MemoryPoolBlock returnEnd = null; lock (_sync) { if (!_disposed) { if (!consumed.IsDefault) { // Compute lengthConsumed before modifying _head or consumed var lengthConsumed = 0; if (_bufferSizeControl != null) { lengthConsumed = new MemoryPoolIterator(_head).GetLength(consumed); } returnStart = _head; returnEnd = consumed.Block; _head = consumed.Block; _head.Start = consumed.Index; // Must call Subtract() after _head has been advanced, to avoid producer starting too early and growing // buffer beyond max length. _bufferSizeControl?.Subtract(lengthConsumed); } if (!examined.IsDefault && examined.IsEnd && RemoteIntakeFin == false && _awaitableError == null) { _manualResetEvent.Reset(); Interlocked.CompareExchange( ref _awaitableState, _awaitableIsNotCompleted, _awaitableIsCompleted); } } else { returnStart = _head; returnEnd = null; _head = null; _tail = null; } ReturnBlocks(returnStart, returnEnd); if (!_consuming) { throw new InvalidOperationException("No ongoing consuming operation to complete."); } _consuming = false; } }
public int GetLength(MemoryPoolIterator end) { if (IsDefault || end.IsDefault) { return(-1); } var block = _block; var index = _index; var length = 0; checked { while (true) { if (block == end._block) { return(length + end._index - index); } else if (block.Next == null) { throw new InvalidOperationException("end did not follow iterator"); } else { length += block.End - index; block = block.Next; index = block.Start; } } } }
public void Reset() { _lockedStart = default(MemoryPoolIterator); _lockedEnd = default(MemoryPoolIterator); _bufferCount = 0; ByteCount = 0; SocketShutdownSend = false; SocketDisconnect = false; WriteStatus = 0; WriteError = null; }
public MemoryPoolIterator ProducingStart() { lock (_returnLock) { Debug.Assert(_lastStart.IsDefault); if (_tail == null) { return(default(MemoryPoolIterator)); } _lastStart = new MemoryPoolIterator(_tail, _tail.End); return(_lastStart); } }
private void LockWrite() { var head = Self._head; var tail = Self._tail; if (head == null || tail == null) { // ReturnAllBlocks has already bee called. Nothing to do here. // Write will no-op since _byteCount will remain 0. return; } _lockedStart = new MemoryPoolIterator(head, head.Start); _lockedEnd = new MemoryPoolIterator(tail, tail.End); BytesBetween(_lockedStart, _lockedEnd, out ByteCount, out _bufferCount); }
public void ProducingComplete(MemoryPoolIterator end) { if (_lastStart.IsDefault) { return; } int bytesProduced, buffersIncluded; BytesBetween(_lastStart, end, out bytesProduced, out buffersIncluded); lock (_contextLock) { _numBytesPreCompleted += bytesProduced; } ProducingCompleteNoPreComplete(end); }
private static void BytesBetween(MemoryPoolIterator start, MemoryPoolIterator end, out int bytes, out int buffers) { if (start.Block == end.Block) { bytes = end.Index - start.Index; buffers = 1; return; } bytes = start.Block.Data.Offset + start.Block.Data.Count - start.Index; buffers = 1; for (var block = start.Block.Next; block != end.Block; block = block.Next) { bytes += block.Data.Count; buffers++; } bytes += end.Index - end.Block.Data.Offset; buffers++; }
public void ProducingComplete(MemoryPoolIterator end) { var block = _producingBlock; while (block != end.Block) { // If we don't handle an exception from _outputStream.Write() here, we'll leak memory blocks. if (_canWrite) { try { _outputStream.Write(block.Data.Array, block.Data.Offset, block.Data.Count); } catch (Exception) { _canWrite = false; } } var returnBlock = block; block = block.Next; returnBlock.Pool.Return(returnBlock); } if (_canWrite) { try { _outputStream.Write(end.Block.Array, end.Block.Data.Offset, end.Index - end.Block.Data.Offset); } catch (Exception) { _canWrite = false; } } end.Block.Pool.Return(end.Block); }