IBlockPool
IBlockPool and IBlockPool<T> are interfaces for types that manage recycleable data bocks. Block size is preconfigured, usually 4096. Having only one block size across the process makes it lot more efficient.
/// <summary>Block pool allocates and recycles memory blocks that are used for buffers.</summary>
public interface IBlockPool
{
/// <summary>Block size, typically 4096</summary>
int BlockSize { get; set; }
/// <summary>Has capability to disconnect block</summary>
bool CanDisconnect { get; }
/// <summary>Element type</summary>
Type ElementType { get; }
}
/// <summary>Block pool allocates and recycles memory blocks that are used for buffers.</summary>
public interface IBlockPool<T> : IBlockPool
{
/// <summary>Try to allocate <paramref name="block"/>, if no blocks are available returns false and null.</summary>
/// <returns>true if <paramref name="block"/> was placed with block, false if there were not free space</returns>
bool TryAllocate(bool cleared, out T[] block);
/// <summary>Allocate block. If no blocks are available, then waits until one is returned.</summary>
/// <returns>block</returns>
T[] Allocate(bool cleared);
/// <summary>
/// Return <paramref name="block"/> back to the block pool.
///
/// If there is a thread waiting to get a block, then the thread is woken up and is distributed the block.
/// </summary>
/// <param name="block">block to return</param>
void Return(T[] block, bool clearContent = true);
/// <summary>
/// Return <paramref name="blocks"/> back to the block pool.
///
/// If there is a thread waiting to get a block, then the thread is woken up and provided one.
/// </summary>
/// <param name="blocks">block to return</param>
void Return(IEnumerable<T[]?> blocks, bool clearContent = true);
/// <summary>
/// Disconnect <paramref name="block"/> from pool. <paramref name="block"/> is a block that has been allocated by the pool earlier on.
///
/// The caller gets the ownership of <paramref name="block"/>.
/// </summary>
/// <param name="block"></param>
void Disconnect(T[] block);
/// <summary>
/// Disconnect <paramref name="blocks"/> from the pool. <paramref name="blocks"/> have been allocated by the pool earlier on.
///
/// The caller gets the ownership of <paramref name="blocks"/>.
/// </summary>
/// <param name="blocks"></param>
void Disconnect(IEnumerable<T[]?> blocks);
}
ArrayBlockPool<T>.Instance is singleton that forwards pooling to ArrayPool<T>.Shared. This is the recommended block pool to use.
IBlockPool<byte> pool = ArrayBlockPool<byte>.Instance;
new ArrayBlockPool<T>(blockSize) creates for specific blockSize. It forwards pooling to ArrayPool<T>.Shared.
IBlockPool<byte> pool = new ArrayBlockPool<byte>(blockSize: 4096);
BlockPool<T>.Instance is singleton for alternative block pool class. This has more features, but doesn't share pool with standard library.
IBlockPool<byte> pool = BlockPool<byte>.Instance;
new BlockPool<T>() creates new block pool.
IBlockPool<byte> pool = new BlockPool<byte>(blockSize: 1024, maxBlockCount: 3, maxRecycleQueue: 3);
PseudoPool<T>.Instance is a pseudo-pool. It doesn't pool anything, but uses new T[] for allocation, and lets blocks be collected by GC.
IBlockPool<byte> pool = PseudoPool<byte>.Instance;
.Allocate(clear) and .Return(clear) acquire and return blocks to and from pool.
// Allocate dirty block
byte[] data = ArrayBlockPool<byte>.Instance.Allocate(cleared: false);
// Return block
ArrayBlockPool<byte>.Instance.Return(data, clearContent: false);
Full Example
Full example
using Avalanche.Memory;
public class blockpool
{
public static void Run()
{
{
// <01>
IBlockPool<byte> pool = ArrayBlockPool<byte>.Instance;
// </01>
}
{
// <02>
IBlockPool<byte> pool = new ArrayBlockPool<byte>(blockSize: 4096);
// </02>
}
{
// <03>
IBlockPool<byte> pool = BlockPool<byte>.Instance;
// </03>
}
{
// <04>
IBlockPool<byte> pool = new BlockPool<byte>(blockSize: 1024, maxBlockCount: 3, maxRecycleQueue: 3);
// </04>
}
{
// <05>
IBlockPool<byte> pool = PseudoPool<byte>.Instance;
// </05>
}
{
// <06>
// Allocate dirty block
byte[] data = ArrayBlockPool<byte>.Instance.Allocate(cleared: false);
// Return block
ArrayBlockPool<byte>.Instance.Return(data, clearContent: false);
// </06>
}
}
}