using System ;
using System.Runtime.CompilerServices ;
using System.Threading ;
/*https://github.com/dotnet/aspnetcore/blob/main/src/ObjectPool*/
namespace MemoryPools
{
/// <summary>
/// Default implementation of <see cref="ObjectPool{T}"/>.
/// </summary>
/// <typeparam name="T">The type to pool objects for.</typeparam>
/// <remarks>This implementation keeps a cache of retained objects. This means that if objects are returned when the pool has already reached "maximumRetained" objects they will be available to be Garbage Collected.</remarks>
public class DefaultObjectPool < T > : ObjectPool < T > where T : class
{
private protected readonly ObjectWrapper [ ] _items ;
private protected readonly IPooledObjectPolicy < T > _policy ;
private protected readonly bool _isDefaultPolicy ;
private protected T _firstItem ;
// This class was introduced in 2.1 to avoid the interface call where possible
private protected readonly PooledObjectPolicy < T > _fastPolicy ;
/// <summary>
/// Creates an instance of <see cref="DefaultObjectPool{T}"/>.
/// </summary>
/// <param name="policy">The pooling policy to use.</param>
public DefaultObjectPool ( IPooledObjectPolicy < T > policy )
: this ( policy , Environment . ProcessorCount * 2 )
{
}
/// <summary>
/// Creates an instance of <see cref="DefaultObjectPool{T}"/>.
/// </summary>
/// <param name="policy">The pooling policy to use.</param>
/// <param name="maximumRetained">The maximum number of objects to retain in the pool.</param>
public DefaultObjectPool ( IPooledObjectPolicy < T > policy , int maximumRetained )
{
_policy = policy ? ? throw new ArgumentNullException ( nameof ( policy ) ) ;
_fastPolicy = ( policy as PooledObjectPolicy < T > ) ! ;
_isDefaultPolicy = IsDefaultPolicy ( ) ;
// -1 due to _firstItem
_items = new ObjectWrapper [ maximumRetained - 1 ] ;
bool IsDefaultPolicy ( )
{
var type = policy . GetType ( ) ;
return type . IsGenericType & & type . GetGenericTypeDefinition ( ) = = typeof ( DefaultPooledObjectPolicy < > ) ;
}
}
/// <inheritdoc />
public override T Get ( )
{
var item = _firstItem ;
if ( item = = null | | Interlocked . CompareExchange ( ref _firstItem ! , null , item ) ! = item )
{
var items = _items ;
for ( var i = 0 ; i < items . Length ; i + + )
{
item = items [ i ] . Element ;
if ( item ! = null & & Interlocked . CompareExchange ( ref items [ i ] . Element ! , null , item ) = = item )
{
return item ;
}
}
item = Create ( ) ;
}
return item ;
}
// Non-inline to improve its code quality as uncommon path
[MethodImpl(MethodImplOptions.NoInlining)]
private T Create ( ) = > _fastPolicy ? . Create ( ) ? ? _policy . Create ( ) ;
/// <inheritdoc />
public override void Return ( T obj )
{
if ( _isDefaultPolicy | | ( _fastPolicy ? . Return ( obj ) ? ? _policy . Return ( obj ) ) )
{
if ( _firstItem ! = null | | Interlocked . CompareExchange ( ref _firstItem , obj , null ) ! = null ! )
{
var items = _items ;
for ( var i = 0 ; i < items . Length & & Interlocked . CompareExchange ( ref items [ i ] . Element , obj , null ) ! = null ! ; + + i )
{
}
}
}
}
private protected struct ObjectWrapper
{
public T Element ;
}
}
}