/// <summary> /// Gets an existing element from pool or creates a new element if required. /// </summary> /// <param name="timeout">Timeout</param> /// <param name="token">Cancellation token</param> /// <returns>Element in case of success. Otherwise null.</returns> private PoolElementWrapper <TElem> TryGetElement(int timeout, CancellationToken token) { if (_disposeCancellation.IsCancellationRequested || token.IsCancellationRequested) { return(null); } PoolElementWrapper <TElem> result = null; while (_elementsContainer.TryTake(out result, 0, new CancellationToken())) { if (ProcessTakenElement(ref result)) { CreateNewInsteadOfTakenIfRequired(ref result, timeout, token); return(result); } } if (timeout == 0) { return(null); } uint startTime = timeout > 0 ? GetTimestamp() : 0; int restTime = timeout; while (timeout < 0 || restTime > 0) { if (_disposeCancellation.IsCancellationRequested || token.IsCancellationRequested) { return(null); } result = TryCreateNewElement(restTime, token); if (result != null) { return(result); } restTime = UpdateTimeout(startTime, timeout); restTime = restTime > 0 ? Math.Min(_getRetryTimeout, restTime) : _getRetryTimeout; if (_elementsContainer.TryTake(out result, restTime, token)) { if (ProcessTakenElement(ref result)) { return(result); } } restTime = UpdateTimeout(startTime, timeout); } return(null); }
/// <summary> /// Takes element from the <see cref="_elementsContainer"/> then destroys it and removes from the Pool /// </summary> /// <returns>Whether the element was presented in <see cref="_elementsContainer"/></returns> private bool TakeDestroyAndRemoveElement() { PoolElementWrapper <TElem> element = null; if (_elementsContainer.TryTake(out element, 0, new CancellationToken())) { DestroyAndRemoveElement(element); return(true); } return(false); }
public void TestTakeBlocks() { PrioritizedElementsContainer <int> testInst = new PrioritizedElementsContainer <int>(new PoolElementComparer()); CancellationTokenSource tokSrc = new CancellationTokenSource(); bool wasCancelled = false; bool wasEntered = false; bool wasExited = false; Task.Run(() => { try { Volatile.Write(ref wasEntered, true); PoolElementWrapper <int> item; testInst.TryTake(out item, -1, tokSrc.Token); } catch (OperationCanceledException) { Volatile.Write(ref wasCancelled, true); } Volatile.Write(ref wasExited, true); }); TimingAssert.IsTrue(10000, () => Volatile.Read(ref wasEntered)); Thread.Sleep(100); Assert.IsFalse(Volatile.Read(ref wasExited)); tokSrc.Cancel(); TimingAssert.IsTrue(10000, () => Volatile.Read(ref wasExited)); Assert.IsTrue(Volatile.Read(ref wasCancelled)); }
public void TestTakeUntilEmpty() { PrioritizedElementsContainer <int> testInst = new PrioritizedElementsContainer <int>(new PoolElementComparer()); try { for (int i = 0; i < 10; i++) { testInst.Add(i, new PoolOperations(), true); } List <PoolElementWrapper <int> > takenElems = new List <PoolElementWrapper <int> >(); PoolElementWrapper <int> item; for (int i = 0; i < 10; i++) { bool takeRes = testInst.TryTake(out item, 0, new CancellationToken()); takenElems.Add(item); Assert.IsTrue(takeRes); Assert.IsNotNull(item); Assert.IsTrue(item.IsBusy); } Assert.AreEqual(0, testInst.AvailableCount); bool takeResO = testInst.TryTake(out item, 0, new CancellationToken()); Assert.IsFalse(takeResO); for (int i = 0; i < takenElems.Count; i++) { testInst.Release(takenElems[i]); } } finally { testInst.ProcessAllElements(o => o.MarkElementDestroyed()); } }
private static void RunTestObjectPoolWithSyncPrior(int threadCount, int elemCount, int opCount, int pauseSpin) { PrioritizedElementsContainer <PoolElem> pool = new PrioritizedElementsContainer <PoolElem>(new PoolElemComparerNew()); for (int i = 0; i < elemCount; i++) { pool.Add(new PoolElem(), new PoolElemOpSup(), true); } TestObjectPoolWithSyncPrior(pool, threadCount, opCount, pauseSpin); PoolElementWrapper <PoolElem> tmp; while (pool.TryTake(out tmp, 0, new CancellationToken())) { tmp.MarkElementDestroyed(); pool.Release(tmp); } }
public void TestTakeByPriority() { PrioritizedElementsContainer <int> testInst = new PrioritizedElementsContainer <int>(new PoolElementComparer()); try { Random rnd = new Random(); for (int i = 0; i < 100; i++) { testInst.Add(rnd.Next(), new PoolOperations(), true); } List <PoolElementWrapper <int> > takenElems = new List <PoolElementWrapper <int> >(); PoolElementWrapper <int> item; for (int i = 0; i < 100; i++) { bool takeRes = testInst.TryTake(out item, 0, new CancellationToken()); takenElems.Add(item); Assert.IsTrue(takeRes); Assert.IsNotNull(item); Assert.IsTrue(item.IsBusy); } for (int i = 0; i < takenElems.Count - 1; i++) { Assert.IsTrue(takenElems[i].Element > takenElems[i + 1].Element); } for (int i = 0; i < takenElems.Count; i++) { testInst.Release(takenElems[i]); } } finally { testInst.ProcessAllElements(o => o.MarkElementDestroyed()); } }
public void TestRemoveOnTake() { PrioritizedElementsContainer <int> testInst = new PrioritizedElementsContainer <int>(new PoolElementComparer()); try { for (int i = 0; i < 10; i++) { testInst.Add(i, new PoolOperations(), true); } testInst.ProcessAllElements(o => o.MarkElementDestroyed()); PoolElementWrapper <int> item; bool takeResult = testInst.TryTake(out item, 0, new CancellationToken()); Assert.IsFalse(takeResult); Assert.AreEqual(0, testInst.Count); } finally { testInst.ProcessAllElements(o => o.MarkElementDestroyed()); } }