public void ServiceCouldGrowBucketsWithResize() { // 2 counters per bucket Settings.AtomicCounterPoolBucketSize = 4; // 4 buckets initially var count = 100; var counters = new List <AtomicCounter>(); for (int i = 0; i < count; i++) { counters.Add(AtomicCounterService.AcquireCounter()); } foreach (var atomicCounter in counters) { atomicCounter.Dispose(); AtomicCounterService.ReleaseCounter(atomicCounter); } Assert.AreEqual(64, AtomicCounterService.Buckets.Length); Assert.AreEqual(50, AtomicCounterService.Buckets.Where(x => x != null).Count()); Assert.AreEqual(50 * 2, AtomicCounterService.Buckets.Where(x => x != null).Select(x => x.FreeCount).Sum()); }
// ReSharper disable once InconsistentNaming public void ServiceCouldCreateACPoolAndAcquireRelease() { Settings.AtomicCounterPoolBucketSize = 4; var ac = AtomicCounterService.AcquireCounter(); var ac1 = AtomicCounterService.AcquireCounter(); Assert.IsTrue(ac.IsValid); Assert.AreEqual(1, ac.Increment()); Assert.AreEqual(0, ac.Decrement()); Assert.AreEqual(1, ac.Increment()); Assert.Throws <InvalidOperationException>(() => ac.Dispose()); Assert.AreEqual(0, ac.Decrement()); Assert.Throws <InvalidOperationException>(() => AtomicCounterService.ReleaseCounter(ac)); ac.Dispose(); ac1.Dispose(); Assert.Throws <ObjectDisposedException>(() => ac.Increment()); Assert.Throws <ObjectDisposedException>(() => ac1.Increment()); AtomicCounterService.ReleaseCounter(ac); }
protected override void Dispose(bool disposing) { if (_externallyOwned) { ThrowHelper.ThrowNotSupportedException(); } EnsureNotRetainedAndNotDisposed(); // disposing == false when finalizing and detected that non pooled if (disposing) { TryReturnThisToPoolOrFinalize(); } else { Debug.Assert(!_isPooled); _pool = null; // we still could add this to the pool of free pinned slices that are backed by an existing slab var pooledToFreeSlicesPool = _slicesPool.Return(this); if (pooledToFreeSlicesPool) { return; } Counter.Dispose(); AtomicCounterService.ReleaseCounter(Counter); ClearAfterDispose(); // destroy the object and release resources var array = Interlocked.Exchange(ref _array, null); if (array != null) { Debug.Assert(_handle.IsAllocated); #pragma warning disable 618 _slab.Decrement(); _handle.Free(); #pragma warning restore 618 } else { ThrowDisposed <ArrayMemory <T> >(); } Debug.Assert(!_handle.IsAllocated); } }
public void ServiceBenchmark() { var count = 10000; Settings.AtomicCounterPoolBucketSize = count; var rounds = 5000; var counters = new List <AtomicCounter>(); using (Benchmark.Run("Service FullCycle", count * (long)rounds)) { for (int r = 0; r < rounds; r++) { for (int i = 0; i < count; i++) { counters.Add(AtomicCounterService.AcquireCounter()); } for (int i = counters.Count - 1; i >= 0; i--) { var atomicCounter = counters[i]; atomicCounter.Dispose(); AtomicCounterService.ReleaseCounter(atomicCounter); } //foreach (var atomicCounter in counters) //{ // atomicCounter.Dispose(); // AtomicCounterService.ReleaseCounter(atomicCounter); //} counters.Clear(); } } Assert.AreEqual(4, AtomicCounterService.Buckets.Length); Assert.AreEqual(1, AtomicCounterService.Buckets.Where(x => x != null).Count()); }
protected override void Dispose(bool disposing) { EnsureNotRetainedAndNotDisposed(); // disposing == false when finilizing and detected that non pooled if (disposing) { TryReturnThisToPoolOrFinalize(); } else { Debug.Assert(!_isPooled); _pool = null; Counter.Dispose(); AtomicCounterService.ReleaseCounter(Counter); ClearAfterDispose(); // Dispose destructs this object and native buffer _offHeapBuffer.Dispose(); // set all to default, increase chances to detect errors _offHeapBuffer = default; } }