public void MultipleReleaseAtDifferentThreadTest() { ThreadLocalPool <HandledObject> pool = NewPool(1024); HandledObject obj = pool.Take(); Thread thread = new Thread(() => { obj.Release(); }); thread.Start(); thread.Join(); ExceptionDispatchInfo exceptionDispatchInfo = null; Thread thread2 = new Thread(() => { try { obj.Release(); } catch (Exception ex) { Interlocked.Exchange(ref exceptionDispatchInfo, ExceptionDispatchInfo.Capture(ex)); } }); thread2.Start(); thread2.Join(); var exception = Assert.ThrowsAny <InvalidOperationException>(() => Volatile.Read(ref exceptionDispatchInfo)?.Throw()); Assert.True(exception != null); }
PooledByteBuffer(ThreadLocalPool.Handle returnHandle, IByteBufferAllocator allocator, byte[] pooledArray, int maxCapacity) : base(allocator, pooledArray, 0, 0, maxCapacity) { this.length = pooledArray.Length; this.returnHandle = returnHandle; this.pooledArray = pooledArray; }
public void MultipleReleaseTest() { ThreadLocalPool <HandledObject> pool = NewPool(1024); HandledObject obj = pool.Take(); obj.Release(); var exception = Assert.ThrowsAny <InvalidOperationException>(() => obj.Release()); Assert.True(exception != null); }
public PooledByteBufferAllocator(int maxPooledBufSize, int maxLocalPoolSize) { Contract.Requires(maxLocalPoolSize > maxPooledBufSize); this.MaxPooledBufSize = maxPooledBufSize; this.pool = new ThreadLocalPool <PooledByteBuffer>( handle => new PooledByteBuffer(handle, this, maxPooledBufSize, int.MaxValue), maxLocalPoolSize / maxPooledBufSize, false); // todo: prepare }
public PooledByteBufferAllocator(int maxPooledBufSize, int maxLocalPoolSize) { Contract.Requires(maxLocalPoolSize > maxPooledBufSize); this.MaxPooledBufSize = maxPooledBufSize; this.pool = new ThreadLocalPool<PooledByteBuffer>( handle => new PooledByteBuffer(handle, this, maxPooledBufSize, int.MaxValue), maxLocalPoolSize / maxPooledBufSize, false); }
public void ReleaseDisableTest() { ThreadLocalPool <HandledObject> pool = NewPool(-1); HandledObject obj = pool.Take(); obj.Release(); HandledObject obj2 = pool.Take(); Assert.NotSame(obj, obj2); obj2.Release(); }
private static ThreadLocalPool <AbstractPoolObject> Register <T>(Type type) where T : AbstractPoolObject { var pool = new ThreadLocalPool <AbstractPoolObject>(handle => { var t = Activator.CreateInstance(type) as T; t.RecyclerHandle = handle; return(t); }); recycler.TryAdd(type, pool); return(pool); }
internal Stack(ThreadLocalPool parent, Thread thread, int maxCapacity, int maxSharedCapacityFactor, int interval, int maxDelayedQueues, int delayedQueueInterval) { _parent = parent; _threadRef = new WeakReference <Thread>(thread); _maxCapacity = maxCapacity; _availableSharedCapacity = new StrongBox <int>(Math.Max(maxCapacity / maxSharedCapacityFactor, LinkCapacity)); _elements = new DefaultHandle[Math.Min(DefaultInitialCapacity, maxCapacity)]; _interval = interval; _delayedQueueInterval = delayedQueueInterval; _handleRecycleCount = interval; // Start at interval so the first one will be recycled. _maxDelayedQueues = maxDelayedQueues; }
public void DiscardingExceedingElementsWithReleaseAtDifferentThreadTest() { int maxCapacity = 32; int instancesCount = 0; ThreadLocalPool <HandledObject> pool = new ThreadLocalPool <HandledObject>(handle => { Interlocked.Increment(ref instancesCount); return(new HandledObject(handle)); }, maxCapacity, 2); // Borrow 2 * maxCapacity objects. HandledObject[] array = new HandledObject[maxCapacity * 2]; for (int i = 0; i < array.Length; i++) { array[i] = pool.Take(); } Assert.Equal(array.Length, Volatile.Read(ref instancesCount)); // Reset counter. Interlocked.Exchange(ref instancesCount, 0); // Release from other thread. Thread thread = new Thread(() => { for (int i = 0; i < array.Length; i++) { array[i].Release(); } }); thread.Start(); thread.Join(); Assert.Equal(0, Volatile.Read(ref instancesCount)); // Borrow 2 * maxCapacity objects. Half of them should come from // the recycler queue, the other half should be freshly allocated. for (int i = 0; i < array.Length; i++) { array[i] = pool.Take(); } // The implementation uses maxCapacity / 2 as limit per WeakOrderQueue Assert.True(array.Length - maxCapacity / 2 <= Volatile.Read(ref instancesCount), "The instances count (" + Volatile.Read(ref instancesCount) + ") must be <= array.length (" + array.Length + ") - maxCapacity (" + maxCapacity + ") / 2 as we not pool all new handles" + " internally"); }
public void ThreadCanBeCollectedEvenIfHandledObjectIsReferencedTest() { ThreadLocalPool <HandledObject> pool = NewPool(1024); HandledObject reference = null; WeakReference <Thread> threadRef = null; WeakReference <XThread> xThreadRef = null; var thread1 = new Thread(() => { //Don't know the reason, but thread2 will not be collected without wrapped with thread1 var thread2 = new Thread(() => { Interlocked.Exchange(ref xThreadRef, new WeakReference <XThread>(XThread.CurrentThread)); HandledObject data = pool.Take(); // Store a reference to the HandledObject to ensure it is not collected when the run method finish. Interlocked.Exchange(ref reference, data); }); Interlocked.Exchange(ref threadRef, new WeakReference <Thread>(thread2)); thread2.Start(); thread2.Join(); Assert.True(Volatile.Read(ref threadRef)?.TryGetTarget(out _)); Assert.True(Volatile.Read(ref xThreadRef)?.TryGetTarget(out _)); GC.KeepAlive(thread2); // Null out so it can be collected. thread2 = null; }); thread1.Start(); thread1.Join(); for (int i = 0; i < 5; ++i) { GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true); GC.WaitForPendingFinalizers(); if (Volatile.Read(ref threadRef)?.TryGetTarget(out _) == true || Volatile.Read(ref xThreadRef)?.TryGetTarget(out _) == true) { Thread.Sleep(100); } } Assert.False(Volatile.Read(ref threadRef)?.TryGetTarget(out _)); Assert.False(Volatile.Read(ref xThreadRef)?.TryGetTarget(out _)); // Now call recycle after the Thread was collected to ensure this still works... reference.Release(); reference = null; }
public void RecycleDisableDrop() { ThreadLocalPool <HandledObject> recycler = NewPool(1024, 2, 0, 2, 0); HandledObject obj = recycler.Take(); obj.Release(); HandledObject obj2 = recycler.Take(); Assert.Same(obj, obj2); obj2.Release(); HandledObject obj3 = recycler.Take(); Assert.Same(obj, obj3); obj3.Release(); }
public void RecycleDisableDelayedQueueDrop() { ThreadLocalPool <HandledObject> recycler = NewPool(1024, 2, 1, 2, 0); HandledObject o = recycler.Take(); HandledObject o2 = recycler.Take(); HandledObject o3 = recycler.Take(); Task.Run(() => { o.Release(); o2.Release(); o3.Release(); }).Wait(); // In reverse order Assert.Same(o3, recycler.Take()); Assert.Same(o, recycler.Take()); }
protected LoopExecutor(IEventLoopGroup parent, IThreadFactory threadFactory, IRejectedExecutionHandler rejectedHandler, TimeSpan breakoutInterval) : base(parent, threadFactory, false, int.MaxValue, rejectedHandler) { _writeRequestPool = new ThreadLocalPool <WriteRequest>(s_valueFactory); _preciseBreakoutInterval = ToPreciseTime(breakoutInterval); _loop = new Loop(); _asyncHandle = new Async(_loop, OnCallbackAction, this); _timerHandle = new Timer(_loop, OnCallbackAction, this); _loopRunStart = new ManualResetEventSlim(false, 1); if (SharedConstants.False >= (uint)Interlocked.Exchange(ref s_startTimeInitialized, SharedConstants.True)) { _loop.UpdateTime(); s_initialTime = _loop.Now; } }
void MaxCapacityTest0(int maxCapacity) { var recycler = new ThreadLocalPool <HandledObject>(handle => new HandledObject(handle), maxCapacity); var objects = new HandledObject[maxCapacity * 3]; for (int i = 0; i < objects.Length; i++) { objects[i] = recycler.Take(); } for (int i = 0; i < objects.Length; i++) { objects[i].Release(); objects[i] = null; } Assert.Equal(maxCapacity, recycler.ThreadLocalCapacity); }
public void ReleaseAtDifferentThreadTest() { ThreadLocalPool <HandledObject> pool = NewPool(256, 10, 2, 10, 2); HandledObject obj = pool.Take(); HandledObject obj2 = pool.Take(); Thread thread = new Thread(() => { obj.Release(); obj2.Release(); }); thread.Start(); thread.Join(); Assert.Same(pool.Take(), obj); Assert.NotSame(pool.Take(), obj2); }
public void MaxCapacityWithRecycleAtDifferentThreadTest() { const int maxCapacity = 4; // Choose the number smaller than WeakOrderQueue.LINK_CAPACITY var recycler = new ThreadLocalPool <HandledObject>(handle => new HandledObject(handle), maxCapacity); // Borrow 2 * maxCapacity objects. // Return the half from the same thread. // Return the other half from the different thread. var array = new HandledObject[maxCapacity * 3]; for (int i = 0; i < array.Length; i++) { array[i] = recycler.Take(); } for (int i = 0; i < maxCapacity; i++) { array[i].Release(); } Task.Run(() => { for (int i = maxCapacity; i < array.Length; i++) { array[i].Release(); } }).Wait(); Assert.Equal(recycler.ThreadLocalCapacity, maxCapacity); Assert.Equal(recycler.ThreadLocalSize, maxCapacity); for (int i = 0; i < array.Length; i++) { recycler.Take(); } Assert.Equal(maxCapacity, recycler.ThreadLocalCapacity); Assert.Equal(0, recycler.ThreadLocalSize); }
public PooledByteBuffer(ThreadLocalPool.Handle returnHandle, IByteBufferAllocator allocator, int maxFixedCapacity, int maxCapacity) : this(returnHandle, allocator, new byte[maxFixedCapacity], maxCapacity) { }
PendingWrite(ThreadLocalPool.Handle handle) { this.handle = handle; }
public void MaxCapacityWithRecycleAtDifferentThreadTest() { const int maxCapacity = 4; // Choose the number smaller than WeakOrderQueue.LINK_CAPACITY var recycler = new ThreadLocalPool<HandledObject>(handle => new HandledObject(handle), maxCapacity); // Borrow 2 * maxCapacity objects. // Return the half from the same thread. // Return the other half from the different thread. var array = new HandledObject[maxCapacity * 3]; for (int i = 0; i < array.Length; i++) { array[i] = recycler.Take(); } for (int i = 0; i < maxCapacity; i++) { array[i].Release(); } Task.Run(() => { for (int i = maxCapacity; i < array.Length; i++) { array[i].Release(); } }).Wait(); Assert.Equal(recycler.ThreadLocalCapacity, maxCapacity); Assert.Equal(recycler.ThreadLocalSize, maxCapacity); for (int i = 0; i < array.Length; i++) { recycler.Take(); } Assert.Equal(maxCapacity, recycler.ThreadLocalCapacity); Assert.Equal(0, recycler.ThreadLocalSize); }
public RecyclableObject(ThreadLocalPool.Handle handle) { this.handle = handle; }
internal HandledObject(ThreadLocalPool.Handle handle) { this.handle = handle; }
Entry(ThreadLocalPool.Handle handle) { this.handle = handle; }
void MaxCapacityTest(int maxCapacity) { var recycler = new ThreadLocalPool<HandledObject>(handle => new HandledObject(handle), maxCapacity); var objects = new HandledObject[maxCapacity * 3]; for (int i = 0; i < objects.Length; i++) { objects[i] = recycler.Take(); } for (int i = 0; i < objects.Length; i++) { objects[i].Release(); objects[i] = null; } Assert.Equal(maxCapacity, recycler.ThreadLocalCapacity); }