using System; using System.Runtime.CompilerServices; using System.Threading; /*https://github.com/dotnet/aspnetcore/blob/main/src/ObjectPool*/ namespace MemoryPools { /// /// Default implementation of . /// /// The type to pool objects for. /// 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. public class DefaultObjectPool : ObjectPool where T : class { private protected readonly ObjectWrapper[] _items; private protected readonly IPooledObjectPolicy _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? _fastPolicy; /// /// Creates an instance of . /// /// The pooling policy to use. public DefaultObjectPool(IPooledObjectPolicy policy) : this(policy, Environment.ProcessorCount * 2) { } /// /// Creates an instance of . /// /// The pooling policy to use. /// The maximum number of objects to retain in the pool. public DefaultObjectPool(IPooledObjectPolicy policy, int maximumRetained) { _policy = policy ?? throw new ArgumentNullException(nameof(policy)); _fastPolicy = policy as PooledObjectPolicy; _isDefaultPolicy = IsDefaultPolicy(); // -1 due to _firstItem _items = new ObjectWrapper[maximumRetained - 1]; bool IsDefaultPolicy() { var type = policy.GetType(); return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(DefaultPooledObjectPolicy<>); } } /// 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(); /// 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; } } }