Пример #1
0
        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();
            }
        }
Пример #2
0
        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);
            }
        }
Пример #3
0
        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;
            }
        }
Пример #4
0
        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;
                    }
                }
            }
        }
Пример #5
0
            public void Reset()
            {
                _lockedStart = default(MemoryPoolIterator);
                _lockedEnd   = default(MemoryPoolIterator);
                _bufferCount = 0;
                ByteCount    = 0;

                SocketShutdownSend = false;
                SocketDisconnect   = false;

                WriteStatus = 0;
                WriteError  = null;
            }
Пример #6
0
        public MemoryPoolIterator ProducingStart()
        {
            lock (_returnLock)
            {
                Debug.Assert(_lastStart.IsDefault);

                if (_tail == null)
                {
                    return(default(MemoryPoolIterator));
                }

                _lastStart = new MemoryPoolIterator(_tail, _tail.End);

                return(_lastStart);
            }
        }
Пример #7
0
            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);
            }
Пример #8
0
        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);
        }
Пример #9
0
        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++;
        }
Пример #10
0
        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);
        }