예제 #1
0
        protected override void Dispose(bool disposing)
        {
            if (ExternallyOwned)
            {
                ThrowHelper.ThrowNotSupportedException();
            }

            if (disposing)
            {
                var pool = Pool;
                if (pool != null)
                {
                    pool.ReturnInternal(this, clearMemory: !TypeHelper <T> .IsPinnable);
                    // pool calls Dispose(false) if a bucket is full
                    return;
                }

                // not pooled, doing finalization work now
                GC.SuppressFinalize(this);
            }

            // Finalization

            AtomicCounter.Dispose(ref CounterRef);

            Debug.Assert(!_isPooled);
            _poolIdx = default;

            // 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;
            }

            var array = Interlocked.Exchange(ref _array, null);

            if (array != null)
            {
                ClearAfterDispose();
                Debug.Assert(_handle.IsAllocated);
#pragma warning disable 618
                _slab.Decrement();
                _handle.Free();
#pragma warning restore 618
            }
            else
            {
                ThrowDisposed <ArrayMemorySlice <T> >();
            }

            Debug.Assert(!_handle.IsAllocated);
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        public void PoolUnbalancedRentReturn()
        {
            const int            perCoreCapacity = 50;
            Func <DummyPoolable> dummyFactory    = () => new DummyPoolable();
            var perCoreLockedObjectPool          =
                new LockedObjectPool <DummyPoolable>(dummyFactory, perCoreCapacity, allocateOnEmpty: false);

            var queues = Enumerable.Range(0, 4)
                         .Select(x => new SingleProducerSingleConsumerQueue <DummyPoolable>()).ToArray();

            var cts        = new CancellationTokenSource();
            var totalCount = 0L;

            Task[] producers = new Task[queues.Length];
            Task[] consumers = new Task[queues.Length];

            var sw = Stopwatch.StartNew();

            for (int i = 0; i < queues.Length; i++)
            {
                var queue = queues[i];
                producers[i] = Task.Factory.StartNew(() =>
                {
                    var count = 0L;

                    while (!cts.IsCancellationRequested)
                    {
                        var item = perCoreLockedObjectPool.Rent();
                        if (item != null)
                        {
                            queue.Enqueue(item);
                            count++;
                        }
                    }

                    Interlocked.Add(ref totalCount, count);
                });

                consumers[i] = Task.Factory.StartNew(() =>
                {
                    var count = 0L;
                    while (!cts.IsCancellationRequested)
                    {
                        if (queue.TryDequeue(out var item))
                        {
                            perCoreLockedObjectPool.Return(item);
                            count++;
                        }
                    }

                    Interlocked.Add(ref totalCount, count);
                });
            }

            Thread.Sleep(5_000);
            cts.Cancel();
            Task.WaitAll(producers);
            Task.WaitAll(consumers);
            sw.Stop();

            Console.WriteLine(
                $"MOPS: {(totalCount / 1000000.0) / (sw.ElapsedMilliseconds / 1000.0):N2}, Total count: {totalCount:N0}, elapsed: {sw.ElapsedMilliseconds:N0}");
        }