Example #1
0
        public MemoryPoolIterator BeginWrite(int minimumSize = 0)
        {
            MemoryPoolBlock block = null;

            if (_tail != null)
            {
                int remaining = _tail.Data.Offset + _tail.Data.Count - _tail.End;

                if (minimumSize <= remaining && remaining > 0)
                {
                    block = _tail;
                }
            }

            if (block == null)
            {
                block = _memory.Lease();
            }

            lock (_sync)
            {
                if (_head == null)
                {
                    _head = block;
                }
                else if (block != _tail)
                {
                    Volatile.Write(ref _tail.Next, block);
                    _tail = block;
                }

                return(new MemoryPoolIterator(block, block.End));
            }
        }
Example #2
0
        public void Ensure(int count)
        {
            if (_tail == null)
            {
                _tail      = new MemoryBlockSegment(_pool.Lease());
                _tailIndex = _tail.End;
                _head      = _tail;
                _headIndex = _tail.Start;
            }

            Debug.Assert(_tail.Block != null);
            Debug.Assert(_tail.Next == null);
            Debug.Assert(_tail.End == _tailIndex);

            var segment          = _tail;
            var block            = _tail.Block;
            var blockIndex       = _tailIndex;
            var remaining        = count;
            var bytesLeftInBlock = block.Data.Offset + block.Data.Count - blockIndex;

            // If inadequate bytes left or if the segment is readonly
            if (bytesLeftInBlock < count || segment.ReadOnly)
            {
                var nextBlock   = _pool.Lease();
                var nextSegment = new MemoryBlockSegment(nextBlock);
                segment.End = blockIndex;
                Volatile.Write(ref segment.Next, nextSegment);
                segment = nextSegment;
                block   = nextBlock;

                blockIndex = block.Data.Offset;

                segment.End   = blockIndex;
                segment.Block = block;
                _tail         = segment;
                _tailIndex    = blockIndex;
            }
        }
Example #3
0
        public WritableBuffer Alloc(int minimumSize = 0)
        {
            if (Interlocked.CompareExchange(ref _producingState, 1, 0) != 0)
            {
                throw new InvalidOperationException("Already producing.");
            }

            MemoryBlockSegment segment = null;

            if (_tail != null && !_tail.ReadOnly)
            {
                // Try to return the tail so the calling code can append to it
                int remaining = _tail.Block.Data.Offset + _tail.Block.Data.Count - _tail.End;

                if (minimumSize <= remaining)
                {
                    segment = _tail;
                }
            }

            if (segment == null && minimumSize > 0)
            {
                // We're out of tail space so lease a new segment only if the requested size > 0
                segment = new MemoryBlockSegment(_pool.Lease());
            }

            lock (_sync)
            {
                if (_head == null)
                {
                    _head = segment;
                }
                else if (segment != null && segment != _tail)
                {
                    // Append the segment to the tail if it's non-null
                    Volatile.Write(ref _tail.Next, segment);
                    _tail = segment;
                }

                return(new WritableBuffer(this, _pool, segment));
            }
        }