Ejemplo n.º 1
0
        internal RetainedMemory(Memory <T> memory)
        {
            if (MemoryMarshal.TryGetMemoryManager <T, RetainableMemory <T> >(memory, out var manager))
            {
                manager.Increment();
                _manager = manager;
                _start   = 0;
                _length  = memory.Length;
            }
            else if (MemoryMarshal.TryGetArray <T>(memory, out var segment))
            {
                _manager = ArrayMemory <T> .Create(segment.Array, segment.Offset, segment.Count, externallyOwned : true);

                _manager.Increment();
                _start  = 0;
                _length = _manager.Length;
            }
            else
            {
                ThrowNotSupportedMemoryType();
                _manager = default;
                _start   = 0;
                _length  = 0;
            }

#if DETECT_LEAKS
            _finalizeChecker = new PanicOnFinalize();
#endif
        }
Ejemplo n.º 2
0
        public ArrayMemorySliceBucket(int bufferLength, int maxBufferCount)
        {
            if (!BitUtil.IsPowerOfTwo(bufferLength) || bufferLength >= Settings.SlabLength)
            {
                ThrowHelper.ThrowArgumentException("bufferLength must be a power of two max 64MB");
            }

            _bufferLength = bufferLength;
            // NOTE: allocateOnEmpty = true
            _pool = new LockedObjectPool <ArrayMemorySlice <T> >(maxBufferCount, Factory, allocateOnEmpty: true);

            _slab = ArrayMemory <T> .Create(Settings.SlabLength, true);

            _slabFreeCount = _slab.Length / _bufferLength;
        }
Ejemplo n.º 3
0
            internal RetainableMemory <T> CreateNew()
            {
                RetainableMemory <T> buffer;

                if (_pool._disposed)
                {
                    ThrowDisposed <RetainableMemoryPool <T> >();
                }

                if (_factory == null)
                {
                    ArrayMemory <T> arrayMemory;
                    if (_pool._pin && _bufferLength * Unsafe.SizeOf <T>() <= Settings.LARGE_BUFFER_LIMIT)
                    {
                        if (_sliceBucket == null)
                        {
                            _sliceBucket = new ArrayMemorySliceBucket <T>(_bufferLength, _buffers.Length);
                        }

                        arrayMemory = _sliceBucket.RentMemory();
                    }
                    else
                    {
                        arrayMemory = ArrayMemory <T> .Create(_bufferLength, _pool._pin);
                    }

                    arrayMemory._pool = _pool;
                    if (arrayMemory.LengthPow2 != _bufferLength)
                    {
                        // TODO proper exception, this is for args
                        ThrowBadLength();
                    }
                    buffer = arrayMemory;
                }
                else
                {
                    buffer = _factory.Invoke(_pool, _bufferLength);
                }

                if (_pool.IsRentAlwaysClean)
                {
                    buffer.GetSpan().Clear();
                }
                return(buffer);
            }
Ejemplo n.º 4
0
        public unsafe ArrayMemorySlice(ArrayMemory <T> slab, LockedObjectPool <ArrayMemorySlice <T> > slicesPool, int offset, int length)
        {
            if (!TypeHelper <T> .IsPinnable)
            {
                ThrowHelper.FailFast("Do not use slices for not pinnable");
            }

#pragma warning disable 618
            _slab = slab;
            _slab.Increment();
            _pointer = Unsafe.Add <T>(_slab.Pointer, offset);
            _handle  = GCHandle.Alloc(_slab);
#pragma warning restore 618
            _slicesPool  = slicesPool;
            _length      = length;
            _array       = slab._array;
            _arrayOffset = slab._arrayOffset + offset;
        }
Ejemplo n.º 5
0
        private ArrayMemorySlice <T> Factory()
        {
            // the whole purpose is pooling of ArrayMemorySlice, it's OK to lock
            lock (_pool)
            {
                if (_slabFreeCount == 0)
                {
                    // drop previous slab, it is owned by previous slices
                    // and will be returned to the pool when all slices are disposed
                    _slab = ArrayMemory <T> .Create(Settings.SlabLength, true);

                    _slabFreeCount = _slab.Length / _bufferLength;
                }

                var offset = _slab.Length - _slabFreeCount-- *_bufferLength;

                var slice = new ArrayMemorySlice <T>(_slab, _pool, offset, _bufferLength);
                return(slice);
            }
        }
Ejemplo n.º 6
0
        public RetainedMemory(Memory <T> memory, bool pin = true) // TODO pin param added later and before it behaved like with true, but better to change to false and review usage
        {
            if (MemoryMarshal.TryGetMemoryManager <T, RetainableMemory <T> >(memory, out var manager))
            {
                if (!manager.IsPinned && pin)
                {
                    // TODO review. This uses implementation detail of RetainableMemory:
                    // if pointer is null then it is an non-pinned array for which we did not create
                    // a GCHandle (very expensive). Call to Pin() checks if pointer is null and
                    // creates a GCHandle + pointer. Try to avoid pinning non-pooled ArrayMemory
                    // because it is very expensive.
                    manager.Pin();
                }
                else
                {
                    manager.Increment();
                }
                _manager = manager;
                _offset  = 0;
                _length  = memory.Length;
            }
            else if (MemoryMarshal.TryGetArray <T>(memory, out var segment))
            {
                _manager = ArrayMemory <T> .Create(segment.Array, segment.Offset, segment.Count, externallyOwned : true, pin);

                _manager.Increment();
                _offset = 0;
                _length = _manager.Length;
            }
            else
            {
                ThrowNotSupportedMemoryType();
                _manager = default;
                _offset  = 0;
                _length  = 0;
            }

#if DETECT_LEAKS
            _finalizeChecker = new PanicOnFinalize();
#endif
        }
Ejemplo n.º 7
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)));
        }
Ejemplo n.º 8
0
        private RetainableMemory <T> CreateNew(int length)
        {
            if (_disposed)
            {
                ThrowDisposed <RetainableMemoryPool <T> >();
            }

            if (_factory == null)
            {
                var am = ArrayMemory <T> .Create(BufferPool <T> .Rent(length), 0, length, false, _pin, this);

                // am._pool = this;
                return(Unsafe.As <RetainableMemory <T> >(am));
            }

            var buffer = _factory.Invoke(this, length);

            if (IsRentAlwaysClean)
            {
                buffer.GetSpan().Clear();
            }
            return(buffer);
        }