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<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, 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();
            }
            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);
            }
        }
    }
}