< Summary

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

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%22100%
GetPoolForCurrentCore()100%22100%
Get()100%11100%
Return(...)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    {
 34        private class WrappedPool<T>(DefaultObjectPool<T> inner) : IPool<T> where T : class
 35        {
 36            public T Get() => inner.Get();
 37
 38            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()
 42            => 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
 150        public CoreLocalPool(Func<IPool<T>> poolFactory)
 51        {
 152            _numberOfCores = Environment.ProcessorCount;
 153            _pools = new IPool<T>[_numberOfCores];
 654            for (var i = 0; i < _numberOfCores; i++)
 55            {
 256                _pools[i] = poolFactory();
 57            }
 158        }
 59
 60        [ThreadStatic]
 61        private static int _threadPoolIndex; // 0 = uninitialized
 62
 63        private IPool<T> GetPoolForCurrentCore()
 64        {
 200000065            int idx = _threadPoolIndex;
 66
 200000067            if (idx == 0)
 68            {
 69                // +1 because 0 is reserved for “uninitialized”
 170                idx = (Environment.CurrentManagedThreadId % _numberOfCores) + 1;
 171                _threadPoolIndex = idx;
 72            }
 73
 200000074            return _pools[idx - 1];
 75        }
 76
 100000077        public T Get() => GetPoolForCurrentCore().Get();
 78
 100000079        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}