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())); } } }
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)); }
internal static RecyclableMemoryStream Create(RetainedMemory <byte> initialLargeBuffer, int length) { if ((uint)length > (uint)initialLargeBuffer.Length) { ThrowHelper.ThrowArgumentException(nameof(length)); } return(Create(0, initialLargeBuffer, length)); }
public DirectBuffer(RetainedMemory <byte> retainedMemory) { if (!retainedMemory.IsPinned) { ThrowRetainedMemoryNotPinned(); } _length = (IntPtr)retainedMemory.Length; _pointer = (byte *)retainedMemory.Pointer; }
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); }
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))); }
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); }
internal static RecyclableMemoryStream Create(RetainedMemory <byte> initialLargeBuffer) { return(Create(0, initialLargeBuffer, initialLargeBuffer.Length)); }
public DirectBuffer(RetainedMemory <byte> retainedMemory) { _length = retainedMemory.Length; _pointer = (byte *)retainedMemory.Pointer; }