Example #1
0
        /// <summary>
        ///     Internal method called when a block is requested and the pool is empty. It allocates one additional slab, creates all of
        ///     the
        ///     block tracking objects, and adds them all to the pool.
        /// </summary>
        private MemoryPoolBlock AllocateSlab()
        {
#pragma warning disable CA2000 // Dispose objects before losing scope
            var slab = MemoryPoolSlab.Create(_slabLength);
#pragma warning restore CA2000 // Dispose objects before losing scope
            _slabs.Push(slab);

            var basePtr = slab.NativePointer;
            // Page align the blocks
            var offset = (int)((((ulong)basePtr + _blockSize - 1) & ~((uint)_blockSize - 1)) - (ulong)basePtr);

            var blockCount = (_slabLength - offset) / _blockSize;
            Interlocked.Add(ref _totalAllocatedBlocks, blockCount);

            MemoryPoolBlock block = null;

            for (var i = 0; i < blockCount; i++)
            {
                block = new MemoryPoolBlock(this, slab, offset, _blockSize);

                if (i != blockCount - 1) // last block
                {
                    Return(block);
                }

                offset += _blockSize;
            }

            return(block);
        }
Example #2
0
 internal static MemoryPoolBlock Create(
     int offset,
     int length,
     MemoryPool pool,
     MemoryPoolSlab slab)
 {
     return(new MemoryPoolBlock(pool, slab, offset, length));
 }
Example #3
0
        /// <summary>
        /// This object cannot be instantiated outside of the static Create method
        /// </summary>
        protected MemoryPoolBlock(MemoryPool pool, MemoryPoolSlab slab, int offset, int length)
        {
            _offset = offset;
            _length = length;

            Pool = pool;
            Slab = slab;
        }
Example #4
0
        /// <summary>
        /// This object cannot be instantiated outside of the static Create method
        /// </summary>
        internal MemoryPoolBlock(SlabMemoryPool pool, MemoryPoolSlab slab, int offset, int length)
        {
            _offset = offset;
            _length = length;

            Pool = pool;
            Slab = slab;
        }
Example #5
0
        /// <summary>
        /// This object cannot be instantiated outside of the static Create method
        /// </summary>
        internal MemoryPoolBlock(SlabMemoryPool pool, MemoryPoolSlab slab, int offset, int length)
        {
            _offset = offset;
            _length = length;

            Pool = pool;
            Slab = slab;

            Memory = MemoryMarshal.CreateFromPinnedArray(slab.Array, _offset, _length);
        }
Example #6
0
 // This method can ONLY be called from the finalizer of MemoryPoolBlock
 internal void RefreshBlock(MemoryPoolSlab slab, int offset, int length)
 {
     lock (_disposeSync)
     {
         if (!_isDisposed && slab != null && slab.IsActive)
         {
             // Need to make a new object because this one is being finalized
             // Note, this must be called within the _disposeSync lock because the block
             // could be disposed at the same time as the finalizer.
             Return(new MemoryPoolBlock(this, slab, offset, length));
         }
     }
 }
Example #7
0
        /// <summary>
        /// Internal method called when a block is requested and the pool is empty. It allocates one additional slab, creates all of the
        /// block tracking objects, and adds them all to the pool.
        /// </summary>
        private MemoryPoolBlock AllocateSlab()
        {
            var slab = MemoryPoolSlab.Create(_slabLength);

            _slabs.Push(slab);

            var basePtr = slab.NativePointer;
            // Page align the blocks
            var firstOffset = (int)((((ulong)basePtr + (uint)_blockSize - 1) & ~((uint)_blockSize - 1)) - (ulong)basePtr);

            // Ensure page aligned
            Debug.Assert((((ulong)basePtr + (uint)firstOffset) & (uint)(_blockSize - 1)) == 0);

            var blockAllocationLength = ((_slabLength - firstOffset) & ~(_blockSize - 1));
            var offset = firstOffset;

            for (;
                 offset + _blockSize < blockAllocationLength;
                 offset += _blockSize)
            {
                var block = MemoryPoolBlock.Create(
                    offset,
                    _blockSize,
                    this,
                    slab);
#if BLOCK_LEASE_TRACKING
                block.IsLeased = true;
#endif
                Return(block);
            }

            Debug.Assert(offset + _blockSize - firstOffset == blockAllocationLength);
            // return last block rather than adding to pool
            var newBlock = MemoryPoolBlock.Create(
                offset,
                _blockSize,
                this,
                slab);

            return(newBlock);
        }
Example #8
0
        /// <summary>
        /// Internal method called when a block is requested and the pool is empty. It allocates one additional slab, creates all of the
        /// block tracking objects, and adds them all to the pool.
        /// </summary>
        private MemoryPoolBlock AllocateSlab()
        {
            var slab = MemoryPoolSlab.Create(_slabLength);

            _slabs.Push(slab);

            _slabAllocationCallback?.Invoke(slab);
            slab._deallocationCallback = _slabDeallocationCallback;

            var basePtr     = slab.NativePointer;
            var firstOffset = (int)((_blockStride - 1) - ((ulong)(basePtr + _blockStride - 1) % _blockStride));

            var poolAllocationLength = _slabLength - _blockStride;

            var offset = firstOffset;

            for (;
                 offset + _blockLength < poolAllocationLength;
                 offset += _blockStride)
            {
                var block = MemoryPoolBlock.Create(
                    offset,
                    _blockLength,
                    this,
                    slab);
#if BLOCK_LEASE_TRACKING
                block.IsLeased = true;
#endif
                Return(block);
            }

            // return last block rather than adding to pool
            var newBlock = MemoryPoolBlock.Create(
                offset,
                _blockLength,
                this,
                slab);

            return(newBlock);
        }
        /// <summary>
        /// Internal method called when a block is requested and the pool is empty. It allocates one additional slab, creates all of the
        /// block tracking objects, and adds them all to the pool.
        /// </summary>
        private MemoryPoolBlock AllocateSlab()
        {
            var slab = MemoryPoolSlab.Create(_slabLength);

            _slabs.Push(slab);

            // Get the address for alignment
            IntPtr basePtr = Marshal.UnsafeAddrOfPinnedArrayElement(slab.PinnedArray, 0);
            // Page align the blocks
            var offset = (int)((((ulong)basePtr + (uint)_blockSize - 1) & ~((uint)_blockSize - 1)) - (ulong)basePtr);

            // Ensure page aligned
            Debug.Assert(((ulong)basePtr + (uint)offset) % _blockSize == 0);

            var blockCount = (_slabLength - offset) / _blockSize;

            Interlocked.Add(ref _totalAllocatedBlocks, blockCount);

            MemoryPoolBlock block = null;

            for (int i = 0; i < blockCount; i++)
            {
                block = new MemoryPoolBlock(this, slab, offset, _blockSize);

                if (i != blockCount - 1) // last block
                {
#if BLOCK_LEASE_TRACKING
                    block.IsLeased = true;
#endif
                    Return(block);
                }

                offset += _blockSize;
            }

            return(block);
        }