ObjectPool<T>
using System;
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
using System.Threading;
namespace Polly.Utils
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
internal sealed class ObjectPool<T> where T : class
{
internal static readonly int MaxCapacity = Environment.ProcessorCount * 2 - 1;
private readonly Func<ObjectPool<T>, T> _createFunc;
private readonly Func<T, bool> _returnFunc;
private readonly ConcurrentQueue<T> _items = new ConcurrentQueue<T>();
[System.Runtime.CompilerServices.Nullable(2)]
private T _fastItem;
private int _numItems;
public ObjectPool(Func<T> createFunc, Action<T> reset)
: this(createFunc, (Func<T, bool>)delegate(T o) {
reset(o);
return true;
})
{
}
public ObjectPool(Func<T> createFunc, Func<T, bool> returnFunc)
: this((Func<ObjectPool<T>, T>)((ObjectPool<T> _) => createFunc()), returnFunc)
{
}
public ObjectPool(Func<ObjectPool<T>, T> createFunc, Func<T, bool> returnFunc)
{
_createFunc = createFunc;
_returnFunc = returnFunc;
}
public T Get()
{
T result = _fastItem;
if (result == null || Interlocked.CompareExchange<T>(ref _fastItem, (T)null, result) != result) {
if (_items.TryDequeue(out result)) {
Interlocked.Decrement(ref _numItems);
return result;
}
return _createFunc(this);
}
return result;
}
public void Return(T obj)
{
if (_returnFunc(obj) && (_fastItem != null || Interlocked.CompareExchange<T>(ref _fastItem, obj, (T)null) != null)) {
if (Interlocked.Increment(ref _numItems) <= MaxCapacity)
_items.Enqueue(obj);
else
Interlocked.Decrement(ref _numItems);
}
}
}
}