< Summary

Information
Class: CounterpointCollective.Collections.PoolExtensions
Assembly: CounterpointCollective.CoalescingQueue
File(s): /builds/counterpointcollective/prestoprimitives/CoalescingQueue/Collections/Pool.cs
Line coverage
100%
Covered lines: 4
Uncovered lines: 0
Coverable lines: 4
Total lines: 102
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
Get()100%11100%
Return(...)100%11100%
CreateDefaultPool(...)100%11100%

File(s)

/builds/counterpointcollective/prestoprimitives/CoalescingQueue/Collections/Pool.cs

#LineLine coverage
 1using Microsoft.Extensions.ObjectPool;
 2
 3namespace CounterpointCollective.Collections
 4{
 5#pragma warning disable CA1716 // Identifiers should not match keywords
 6
 7    public interface IPool
 8    {
 9        public object Get();
 10        void Return(object v);
 11    }
 12
 13    public interface IPool<T> : IPool where T : class
 14    {
 15
 16        public new T Get();
 17
 18        public void Return(T v);
 19
 20        object IPool.Get()
 21        {
 22            return Get();
 23        }
 24
 25        void IPool.Return(object v)
 26        {
 27            Return((T)v);
 28        }
 29    }
 30#pragma warning restore CA1716 // Identifiers should not match keywords
 31
 32    public static class PoolExtensions
 33    {
 334        private class WrappedPool<T>(DefaultObjectPool<T> inner) : IPool<T> where T : class
 35        {
 100000736            public T Get() => inner.Get();
 37
 100000738            public void Return(T t) => inner.Return(t);
 39        }
 40
 41        public static IPool<T> CreateDefaultPool<T>(this DefaultPooledObjectPolicy<T> p) where T : class, new()
 342            => new WrappedPool<T>(new(p));
 43    }
 44
 45    public sealed class CoreLocalPool<T> : IPool<T> where T : class
 46    {
 47        private readonly int _numberOfCores;
 48        private readonly IPool<T>[] _pools;
 49
 50        public CoreLocalPool(Func<IPool<T>> poolFactory)
 51        {
 52            _numberOfCores = Environment.ProcessorCount;
 53            _pools = new IPool<T>[_numberOfCores];
 54            for (var i = 0; i < _numberOfCores; i++)
 55            {
 56                _pools[i] = poolFactory();
 57            }
 58        }
 59
 60        [ThreadStatic]
 61        private static int _threadPoolIndex; // 0 = uninitialized
 62
 63        private IPool<T> GetPoolForCurrentCore()
 64        {
 65            int idx = _threadPoolIndex;
 66
 67            if (idx == 0)
 68            {
 69                // +1 because 0 is reserved for “uninitialized”
 70                idx = (Environment.CurrentManagedThreadId % _numberOfCores) + 1;
 71                _threadPoolIndex = idx;
 72            }
 73
 74            return _pools[idx - 1];
 75        }
 76
 77        public T Get() => GetPoolForCurrentCore().Get();
 78
 79        public void Return(T v) => GetPoolForCurrentCore().Return(v);
 80    }
 81
 82    public sealed class ConstantPool<T>(T constant) : IPool<T> where T : class
 83    {
 84        public T Get() => constant;
 85        public void Return(T t)
 86        {
 87            if (t is IResettable r)
 88            {
 89                r.TryReset();
 90            }
 91        }
 92    }
 93
 94    public sealed class NoopPool<T> : IPool<T> where T : class, new()
 95    {
 96        public T Get() => new();
 97        public void Return(T t)
 98        {
 99            //no-op
 100        }
 101    }
 102}