예제 #1
0
        private void EnsureCapacity(int newCapacity)
        {
            if (newCapacity > _memoryManager.MaximumStreamCapacity && _memoryManager.MaximumStreamCapacity > 0)
            {
#if DEBUG
                Events.Write.MemoryStreamOverCapacity(newCapacity, _memoryManager.MaximumStreamCapacity, _tag, AllocationStack);
#else
                Events.Write.MemoryStreamOverCapacity(newCapacity, _memoryManager.MaximumStreamCapacity, null, AllocationStack);
#endif
                ThrowHelper.ThrowInvalidOperationException("Requested capacity is too large: " + newCapacity + ". Limit is " + _memoryManager.MaximumStreamCapacity);
            }

            if (!_largeBuffer.IsEmpty)
            {
                if (newCapacity > _largeBuffer.Length)
                {
#if DEBUG
                    var newBuffer = _memoryManager.GetLargeBuffer(newCapacity, _tag);
#else
                    var newBuffer = _memoryManager.GetLargeBuffer(newCapacity, null);
#endif
                    InternalRead(newBuffer, 0, _length, 0);
                    _largeBuffer.Dispose();
                    _largeBuffer = new RetainedMemory <byte>(newBuffer);
                }
            }
            else
            {
                while (CapacityInternal < newCapacity)
                {
                    _blocks.Add((_memoryManager.GetBlock()));
                }
            }
        }
예제 #2
0
        internal static RecyclableMemoryStream Create(Memory <byte> initialLargeBuffer)
        {
            throw new NotImplementedException("After RM refactoring this needs review");
            var rm = new RetainedMemory <byte>(initialLargeBuffer);

            return(Create(0, rm, rm.Length));
        }
예제 #3
0
 internal static RecyclableMemoryStream Create(RetainedMemory <byte> initialLargeBuffer, int length)
 {
     if ((uint)length > (uint)initialLargeBuffer.Length)
     {
         ThrowHelper.ThrowArgumentException(nameof(length));
     }
     return(Create(0, initialLargeBuffer, length));
 }
예제 #4
0
 public DirectBuffer(RetainedMemory <byte> retainedMemory)
 {
     if (!retainedMemory.IsPinned)
     {
         ThrowRetainedMemoryNotPinned();
     }
     _length  = (IntPtr)retainedMemory.Length;
     _pointer = (byte *)retainedMemory.Pointer;
 }
예제 #5
0
        private static RecyclableMemoryStream Create(int requestedSize,
                                                     RetainedMemory <byte> initialLargeBuffer, int length = -1, string tag = null,
                                                     RecyclableMemoryStreamManager memoryManager          = null)
        {
            memoryManager = memoryManager ?? RecyclableMemoryStreamManager.Default;
            var rms = Pool.Rent();

            rms._refCount      = 1;
            rms._memoryManager = memoryManager;
#if DEBUG
            rms._id  = Interlocked.Increment(ref _lastId);
            rms._tag = tag;
#endif
            if (requestedSize < memoryManager.BlockSize)
            {
                requestedSize = memoryManager.BlockSize;
            }

            if (initialLargeBuffer.IsEmpty)
            {
                rms.EnsureCapacity(requestedSize);
            }
            else
            {
                rms._largeBuffer = initialLargeBuffer;
                if (length > 0)
                {
                    if (length > initialLargeBuffer.Length)
                    {
                        ThrowHelper.ThrowArgumentException("length is larger than buffer size");
                    }
                    rms._length = length;
                }
            }

#if DEBUG
            if (rms._memoryManager.GenerateCallStacks)
            {
                rms.AllocationStack = Environment.StackTrace;
            }
            Events.Write.MemoryStreamCreated(rms._id, rms._tag, requestedSize);
#endif
            rms._memoryManager.ReportStreamCreated();

            return(rms);
        }
예제 #6
0
        public Memory <byte> GetMemory()
        {
            CheckDisposed();

            if (!_largeBuffer.IsEmpty)
            {
                return(_largeBuffer.Memory.Slice(0, checked ((int)_length)));
            }

            if (_blocks.Count == 1)
            {
                return(_blocks[0]);
            }

            // Memory needs to reflect the capacity, not the length, because
            // it's possible that people will manipulate the buffer directly
            // and set the length afterward. Capacity sets the expectation
            // for the size of the buffer.
#if DEBUG
            var newBuffer = _memoryManager.GetLargeBuffer(Capacity, _tag);
#else
            var newBuffer = _memoryManager.GetLargeBuffer(Capacity, null);
#endif

            // InternalRead will check for existence of largeBuffer, so make sure we
            // don't set it until after we've copied the data.
            InternalRead(newBuffer, 0, _length, 0);
            _largeBuffer = ArrayMemory <byte> .Create(newBuffer).Retain();

            if (_blocks.Count > 0)
            {
#if DEBUG
                _memoryManager.ReturnBlocks(_blocks, _tag);
#else
                _memoryManager.ReturnBlocks(_blocks, null);
#endif
                _blocks.Clear();
            }

            return(_largeBuffer.Memory.Slice(0, checked ((int)_length)));
        }
예제 #7
0
        protected override void Dispose(bool disposing)
        {
            var remaining = Interlocked.Decrement(ref _refCount);

            if (disposing && remaining > 0)
            {
                return;
            }

            if (remaining < 0)
            {
                string doubleDisposeStack = null;
                if (_memoryManager.GenerateCallStacks)
                {
                    doubleDisposeStack = Environment.StackTrace;
                }
#if DEBUG
                Events.Write.MemoryStreamDoubleDispose(_id, _tag, AllocationStack, DisposeStack,
                                                       doubleDisposeStack);
#endif
                return;
            }

#if DEBUG
            Events.Write.MemoryStreamDisposed(_id, _tag);
            if (_memoryManager.GenerateCallStacks)
            {
                DisposeStack = Environment.StackTrace;
            }
#endif
            if (disposing)
            {
                _memoryManager.ReportStreamDisposed();

                // regardless of Free result below we do not need finalization, we have done cleaning
                GC.SuppressFinalize(this);
            }
            else
            {
                // We're being finalized.
#if DEBUG
                Events.Write.MemoryStreamFinalized(_id, _tag, AllocationStack);
#endif
                if (AppDomain.CurrentDomain.IsFinalizingForUnload())
                {
                    // If we're being finalized because of a shutdown, don't go any further.
                    // We have no idea what's already been cleaned up. Triggering events may cause
                    // a crash.
                    base.Dispose(false);
                    return;
                }
                _memoryManager.ReportStreamFinalized();
            }

            _memoryManager.ReportStreamLength(_length);

            if (!_largeBuffer.IsEmpty)
            {
                _largeBuffer.Dispose();
                _largeBuffer = default;
            }
#if DEBUG
            _memoryManager.ReturnBlocks(_blocks, _tag);
#else
            _memoryManager.ReturnBlocks(_blocks, null);
#endif
            _blocks.Clear();

            _length   = 0;
            _position = 0;
#if DEBUG
            _id  = 0;
            _tag = null;
#endif
            _memoryManager = null;

            base.Dispose(disposing);

            // last operation, prevent race condition (had it with _memoryManager = null when buffer was reused before Dispose finished)
            Pool.Return(this);
        }
예제 #8
0
 internal static RecyclableMemoryStream Create(RetainedMemory <byte> initialLargeBuffer)
 {
     return(Create(0, initialLargeBuffer, initialLargeBuffer.Length));
 }
예제 #9
0
 public DirectBuffer(RetainedMemory <byte> retainedMemory)
 {
     _length  = retainedMemory.Length;
     _pointer = (byte *)retainedMemory.Pointer;
 }