Ejemplo n.º 1
0
        protected override void Dispose(bool disposing)
        {
            // NB this method is called after ensuring that refcount is zero but before
            // cleaning the fields
            BufferPool <T> .Return(Array);

            base.Dispose(disposing);
            Pool.TryAdd(this);
        }
Ejemplo n.º 2
0
        internal byte[] GetBlock()
        {
            var buffer = BufferPool <byte> .Rent(_blockSize);

            if (buffer.Length == _blockSize)
            {
                return(buffer);
            }
            BufferPool <byte> .Return(buffer, false);

            buffer = new byte[_blockSize];
            return(buffer);
        }
Ejemplo n.º 3
0
        protected override void Dispose(bool disposing)
        {
            var array = Interlocked.Exchange(ref _array, null);

            if (array != null)
            {
                _disposed = true;
                BufferPool <T> .Return(array);
            }
            if (disposing)
            {
                Pool.TryAdd(this);
            }
        }
Ejemplo n.º 4
0
        internal void ReturnLargeBuffer(byte[] buffer, string tag)
        {
            if (buffer == null)
            {
                ThrowHelper.ThrowArgumentNullException("buffer");
                return;
            }

            if (!IsLargeBufferMultiple(buffer.Length))
            {
                BufferPool <byte> .Return(buffer);

                return;
            }

            var poolIndex = buffer.Length / _largeBufferMultiple - 1;

            if (poolIndex < _largePools.Length)
            {
                if ((_largePools[poolIndex].Count + 1) * buffer.Length <= MaximumFreeLargePoolBytes ||
                    MaximumFreeLargePoolBytes == 0)
                {
                    _largePools[poolIndex].Push(buffer);
                    Interlocked.Add(ref _largeBufferFreeSize[poolIndex], buffer.Length);
                }
                else
                {
                    Events.Write.MemoryStreamDiscardBuffer(Events.MemoryStreamBufferType.Large, tag,
                                                           Events.MemoryStreamDiscardReason.EnoughFree);
                    ReportLargeBufferDiscarded(Events.MemoryStreamDiscardReason.EnoughFree);
                }
            }
            else
            {
                // This is a non-poolable buffer, but we still want to track its size for inuse
                // analysis. We have space in the inuse array for this.
                poolIndex = _largeBufferInUseSize.Length - 1;

                Events.Write.MemoryStreamDiscardBuffer(Events.MemoryStreamBufferType.Large, tag,
                                                       Events.MemoryStreamDiscardReason.TooLarge);
                ReportLargeBufferDiscarded(Events.MemoryStreamDiscardReason.TooLarge);
            }

            Interlocked.Add(ref _largeBufferInUseSize[poolIndex], -buffer.Length);

            //ReportUsageReport(_smallPoolInUseSize, _smallPoolFreeSize, LargePoolInUseSize, LargePoolFreeSize);
            ReportUsageReport(0, 0, LargePoolInUseSize, LargePoolFreeSize);
        }
Ejemplo n.º 5
0
        internal override unsafe void Free(bool finalizing)
        {
            ThrowHelper.Assert(IsDisposed);

            var array = Interlocked.Exchange(ref _array, null);

            if (array != null)
            {
                ThrowHelper.DebugAssert(TypeHelper <T> .IsReferenceOrContainsReferences);
                if (!finalizing && !ExternallyOwned)
                {
                    BufferPool <T> .Return(Unsafe.As <T[]>(array), clearArray : true);
                }
            }

            var pointer = Interlocked.Exchange(ref _pointer, IntPtr.Zero);

            if (pointer != IntPtr.Zero)
            {
                Mem.Free((byte *)pointer);
                BuffersStatistics.ReleasedNativeMemory.InterlockedAdd(_length);
            }

            // In PM either pointer or array, never both
            if (array == null && pointer == IntPtr.Zero)
            {
                string msg = "Tried to free already freed PrivateMemory";
#if DEBUG
                ThrowHelper.ThrowInvalidOperationException(msg);
#endif
                Trace.TraceWarning(msg);
                return;
            }

            ClearFields();

            // We cannot tell if this object is pooled, so we rely on finalizer
            // that will be called only if the object is not in the pool.
            // But if we tried to pool the buffer to RMP but failed above
            // then we called GC.SuppressFinalize(this)
            // and finalizer won't be called if the object is dropped from ObjectPool.
            // We have done buffer clean-up job and this object could die normally.
            if (!finalizing)
            {
                ObjectPool.Return(this);
            }
        }
Ejemplo n.º 6
0
        internal void ReturnBlocks(List <byte[]> blocks, string tag)
        {
            if (blocks == null)
            {
                ThrowHelper.ThrowArgumentNullException("blocks");
                return;
            }

            if (blocks.Count > 0)
            {
                foreach (var block in blocks)
                {
                    if (block == null || block.Length != BlockSize)
                    {
                        ThrowHelper.ThrowArgumentException("blocks contains buffers that are not BlockSize in length");
                    }

                    BufferPool <byte> .Return(block, false);
                }
            }

            ReportUsageReport(0, 0, LargePoolInUseSize, LargePoolFreeSize);
        }
Ejemplo n.º 7
0
        internal override unsafe void Free(bool finalizing)
        {
            ThrowHelper.Assert(IsDisposed);

            var array = Interlocked.Exchange(ref _array, null);

            if (array != null)
            {
                ThrowHelper.DebugAssert(TypeHelper <T> .IsReferenceOrContainsReferences);

                // Even if we are finalizing the fields are not collected, because this
                // object is reachable and hence the fields are reachable.
                if (!ExternallyOwned)
                {
                    BufferPool <T> .Return(Unsafe.As <T[]>(array), clearArray : true);
                }
            }

            var pointer = Interlocked.Exchange(ref _pointer, IntPtr.Zero);

            if (pointer != IntPtr.Zero)
            {
                // TODO Switch to mimalloc after updating to new release
                Marshal.FreeHGlobal(pointer);
                // Mem.Free((byte*) pointer);
                BuffersStatistics.ReleasedNativeMemory.InterlockedAdd(_length);
            }

            // In PM either pointer or array, never both
            if (array == null && pointer == IntPtr.Zero)
            {
                string msg = "Tried to free already freed PrivateMemory";
#if DEBUG
                ThrowHelper.ThrowInvalidOperationException(msg);
#endif
                Trace.TraceWarning(msg);
                return;
            }

            ClearFields();

            // This instance is clean now.
            // If we are finalizing then resurrect it by placing it to the pool.
            // If we are disposing then also add to the pool.
            var pooled = ObjectPool.Return(this);

            // If we were finalizing but resurrected then the next time
            // the instance is dropped the finalizer will not run,
            // therefore we must re-register.
            if (pooled && finalizing)
            {
                GC.ReRegisterForFinalize(this);
            }

            // If we cannot pool the instance and not running from finalizer
            // then the reference is dropped and finalizer could re-run.
            // In that case suppress it.
            // If not pooled and finalizing then the job is done.
            if (!pooled && !finalizing)
            {
                GC.SuppressFinalize(this);
            }
        }