/// <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); }
internal static MemoryPoolBlock Create( int offset, int length, MemoryPool pool, MemoryPoolSlab slab) { return(new MemoryPoolBlock(pool, slab, offset, length)); }
/// <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; }
/// <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; }
/// <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); }
// 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)); } } }
/// <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); }
/// <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); }