public void TestProducerConsumer() { const int NumIters = 500; SemaphoreLight inst = new SemaphoreLight(0); var task1 = Task.Factory.StartNew(() => { for (int i = 0; i < NumIters; i++) { Assert.IsTrue(inst.Wait(30000)); } Assert.IsFalse(inst.Wait(0)); }, TaskCreationOptions.LongRunning); var task2 = Task.Factory.StartNew(() => { for (int i = 0; i < NumIters; i++) { inst.Release(); } }, TaskCreationOptions.LongRunning); Task.WaitAll(task1, task2); }
public void WaitTest() { const int sleepTime = 200; const int initialCount = 2; var target = new SemaphoreLight(initialCount); var start = DateTime.Now; target.Wait(); target.Wait(); Assert.IsTrue((DateTime.Now - start).TotalMilliseconds < 50); var releaseThread = new Thread( () => { Thread.Sleep(sleepTime); target.Release(); }); releaseThread.Start(); target.Wait(); var end = DateTime.Now; var elapsed = end - start; Assert.IsTrue(elapsed.TotalMilliseconds > 200); Assert.IsTrue(elapsed.TotalMilliseconds < 250); }
public T GetObject() { if (!_sem.Wait(0, new CancellationToken())) { _sem.Wait(); } T item; _objects.TryPop(out item); return(item); //return _objects.TryTake(); //return _objects.Take(); }
public void TestTimeoutWork() { SemaphoreLight inst = new SemaphoreLight(0); Assert.IsFalse(inst.Wait(1000)); Assert.AreEqual(0, inst.CurrentCount); }
public void TestCancellation() { SemaphoreLight inst = new SemaphoreLight(0); CancellationTokenSource tokenSrc = new CancellationTokenSource(); bool cancelled = false; Task.Run(() => { try { inst.Wait(tokenSrc.Token); } catch (OperationCanceledException) { Volatile.Write(ref cancelled, true); Thread.MemoryBarrier(); } }); TimingAssert.IsTrue(5000, () => inst.WaiterCount > 0); Assert.IsFalse(Volatile.Read(ref cancelled)); tokenSrc.Cancel(); TimingAssert.IsTrue(5000, () => Volatile.Read(ref cancelled)); Assert.AreEqual(0, inst.CurrentCount); Assert.AreEqual(0, inst.WaiterCount); }
public void WaitTest() { int initialCount = 0; // TODO: Initialize to an appropriate value SemaphoreLight target = new SemaphoreLight(initialCount); // TODO: Initialize to an appropriate value target.Wait(); Assert.Inconclusive("A method that does not return a value cannot be verified."); }
/// <summary> /// Выбрать элемент из списка свободных /// </summary> /// <param name="element">Выбранный элемент</param> /// <param name="timeout">Таймаут</param> /// <param name="token">Токен отмены</param> /// <returns>Успешность</returns> private bool TryTakeInner(out PoolElementWrapper <T> element, int timeout, CancellationToken token) { element = null; if (token.IsCancellationRequested) { throw new OperationCanceledException(token); } bool waitForSemaphoreWasSuccessful = _occupiedElements.Wait(0); if (waitForSemaphoreWasSuccessful == false && timeout != 0) { waitForSemaphoreWasSuccessful = _occupiedElements.Wait(timeout, token); } if (!waitForSemaphoreWasSuccessful) { return(false); } bool removeSucceeded = false; bool removeFaulted = true; try { //token.ThrowIfCancellationRequested(); // TODO: Refactor the code removeSucceeded = this.TryTakeCore(out element); TurboContract.Assert(removeSucceeded, "Take from underlying collection return false"); removeFaulted = false; } finally { if (!removeSucceeded && removeFaulted) { _occupiedElements.Release(); } } return(removeSucceeded); }
public void TestReleaseWait() { SemaphoreLight inst = new SemaphoreLight(0); Assert.AreEqual(0, inst.CurrentCount); inst.Release(); Assert.AreEqual(1, inst.CurrentCount); Assert.IsTrue(inst.Wait(0)); Assert.AreEqual(0, inst.CurrentCount); }
public bool TryAdd(ThreadPoolWorkItem item, int timeout) { Contract.Requires(item != null); bool freeNodesExist = true; if (_freeNodes != null) { freeNodesExist = _freeNodes.Wait(0); if (freeNodesExist == false && timeout != 0) { freeNodesExist = _freeNodes.Wait(timeout); } } if (freeNodesExist) { _mainQueue.Add(item); _occupiedNodes.Release(); return(true); } return(false); }
public void TestManyReleaseWait() { SemaphoreLight inst = new SemaphoreLight(0); for (int i = 0; i < 100; i++) { Assert.AreEqual(i, inst.CurrentCount); inst.Release(); } for (int i = 100; i > 0; i--) { Assert.AreEqual(i, inst.CurrentCount); Assert.IsTrue(inst.Wait(10)); } Assert.AreEqual(0, inst.CurrentCount); }
public void TestWakeUpOnRelease() { SemaphoreLight inst = new SemaphoreLight(0); bool wakeUp = false; Task.Run(() => { inst.Wait(); wakeUp = true; }); TimingAssert.IsTrue(5000, () => inst.WaiterCount > 0); Assert.IsFalse(wakeUp); inst.Release(); TimingAssert.IsTrue(5000, () => Volatile.Read(ref wakeUp)); Assert.AreEqual(0, inst.CurrentCount); Assert.AreEqual(0, inst.WaiterCount); }
/// <summary> /// Removes completed batch from the head of the queue (inner core method) /// </summary> /// <param name="batch">The batch removed from queue</param> /// <param name="timeout">Removing timeout</param> /// <param name="token">Cancellation token</param> /// <returns>True if the batch was removed</returns> /// <exception cref="OperationCanceledException">Cancellation was requested by token</exception> /// <exception cref="ObjectDisposedException">Queue was disposed</exception> private bool TryTakeInner(out T[] batch, int timeout, CancellationToken token) { if (_isDisposed) { throw new ObjectDisposedException(this.GetType().Name); } if (token.IsCancellationRequested) { throw new OperationCanceledException(token); } batch = null; bool batchTaken = false; bool entered = false; try { if (_occupiedBatches.Wait(timeout, token)) { entered = true; batchTaken = _innerQueue.TryDequeue(out batch); Debug.Assert(batchTaken == true, "Collection is inconsistent"); } } finally { if (!batchTaken && entered) { _occupiedBatches.Release(); } if (batchTaken && _freeNodes != null) { _freeNodes.Release(batch.Length); } } return(batchTaken); }
/// <summary> /// Adds new item to the tail of the queue (inner core method) /// </summary> /// <param name="item">New item</param> /// <param name="timeout">Adding timeout</param> /// <param name="token">Cancellation token</param> /// <returns>Was added sucessufully</returns> /// <exception cref="OperationCanceledException">Cancellation was requested by token</exception> /// <exception cref="ObjectDisposedException">Queue was disposed</exception> private bool TryAddInner(T item, int timeout, CancellationToken token) { if (_isDisposed) { throw new ObjectDisposedException(this.GetType().Name); } if (token.IsCancellationRequested) { throw new OperationCanceledException(token); } bool elementAdded = false; int batchCountIncreased = 0; bool entered = false; try { if (_freeNodes == null || _freeNodes.Wait(timeout, token)) { entered = true; _innerQueue.Enqueue(item, out batchCountIncreased); elementAdded = true; } } finally { if (!elementAdded && entered && _freeNodes != null) { _freeNodes.Release(); } if (elementAdded && batchCountIncreased > 0) { _occupiedBatches.Release(batchCountIncreased); } } return(elementAdded); }
public void OverflowTest() { SemaphoreLight inst = new SemaphoreLight(0); inst.Release(int.MaxValue - 100); Assert.AreEqual(int.MaxValue - 100, inst.CurrentCount); inst.Release(100); Assert.AreEqual(int.MaxValue, inst.CurrentCount); try { inst.Release(); Assert.Fail("SemaphoreFullException expected"); } catch (SemaphoreFullException) { } bool waitResult = inst.Wait(0); Assert.IsTrue(waitResult); }
private void RunComplexTest(SemaphoreLight sem, int elemCount, int thCount) { int atomicRandom = 0; int trackElemCount = elemCount; int waitedTimesCount = 0; int addFinished = 0; Thread[] threadsTake = new Thread[thCount]; Thread[] threadsAdd = new Thread[thCount]; CancellationTokenSource tokSrc = new CancellationTokenSource(); Action addAction = () => { Random rnd = new Random(Environment.TickCount + Interlocked.Increment(ref atomicRandom) * thCount * 2); while (true) { int item = Interlocked.Decrement(ref trackElemCount); if (item < 0) { break; } sem.Release(); int sleepTime = rnd.Next(100); if (sleepTime > 0) { Thread.SpinWait(sleepTime); } } Interlocked.Increment(ref addFinished); }; Action takeAction = () => { Random rnd = new Random(Environment.TickCount + Interlocked.Increment(ref atomicRandom) * thCount * 2); try { while (Volatile.Read(ref addFinished) < thCount) { sem.Wait(tokSrc.Token); Interlocked.Increment(ref waitedTimesCount); int sleepTime = rnd.Next(100); if (sleepTime > 0) { Thread.SpinWait(sleepTime); } } } catch (OperationCanceledException) { } TestContext.WriteLine("One take thread exit main cycle"); while (sem.Wait(0)) { Interlocked.Increment(ref waitedTimesCount); } }; for (int i = 0; i < threadsTake.Length; i++) { threadsTake[i] = new Thread(new ThreadStart(takeAction)); } for (int i = 0; i < threadsAdd.Length; i++) { threadsAdd[i] = new Thread(new ThreadStart(addAction)); } for (int i = 0; i < threadsTake.Length; i++) { threadsTake[i].Start(); } for (int i = 0; i < threadsAdd.Length; i++) { threadsAdd[i].Start(); } TestContext.WriteLine("All threads started"); for (int i = 0; i < threadsAdd.Length; i++) { threadsAdd[i].Join(); } TestContext.WriteLine("All add threads stopped"); tokSrc.Cancel(); TestContext.WriteLine("Cancell called"); for (int i = 0; i < threadsTake.Length; i++) { threadsTake[i].Join(); } TestContext.WriteLine("All take threads stopped"); Assert.AreEqual(elemCount, waitedTimesCount); }
/// <summary> /// Попытаться получить элемент из главной очереди /// </summary> /// <param name="item">Полученный элемент</param> /// <param name="timeout">Таймаут</param> /// <param name="token">Токен отмены</param> /// <param name="throwOnCancellation">Выбрасывать ли исключение при отмене по токену</param> /// <returns>Удалось ли получить</returns> public bool TryTake(out ThreadPoolWorkItem item, int timeout, CancellationToken token, bool throwOnCancellation) { Contract.Ensures(Contract.Result <bool>() == false || Contract.ValueAtReturn(out item) != null); item = null; if (token.IsCancellationRequested) { if (throwOnCancellation) { throw new OperationCanceledException(token); } return(false); } bool occupiedNodesExist = _occupiedNodes.Wait(0); if (occupiedNodesExist == false && timeout != 0) { occupiedNodesExist = _occupiedNodes.Wait(timeout, token, throwOnCancellation); } if (occupiedNodesExist) { bool wasElementTaken = false; bool takePerformed = true; try { if (token.IsCancellationRequested) { if (throwOnCancellation) { throw new OperationCanceledException(token); } return(false); } wasElementTaken = _mainQueue.TryTake(out item); takePerformed = false; Debug.Assert(wasElementTaken, "Incorrect collection state. Can't take items from collection when they should be there"); } finally { if (wasElementTaken) { if (_freeNodes != null) { // Не освобождаем, если запрошен экстеншн if (Volatile.Read(ref _extendedCapacityRequest) <= 0 || Interlocked.Decrement(ref _extendedCapacityRequest) < 0) { _freeNodes.Release(); } } } else { if (takePerformed) { _occupiedNodes.Release(); } } } } return(occupiedNodesExist); }
private static TimeSpan TestSemaphoreLight(string name, int elemCount, int addThCount, int takeThCount, int addSpin, int takeSpin) { SemaphoreLight sem = new SemaphoreLight(0, int.MaxValue); CancellationTokenSource srcCancel = new CancellationTokenSource(); Thread[] addThreads = new Thread[addThCount]; Thread[] takeThreads = new Thread[takeThCount]; int addedElemCount = 0; Barrier barierStart = new Barrier(1 + addThreads.Length + takeThreads.Length); Barrier barierAdders = new Barrier(1 + addThreads.Length); Barrier barierTakers = new Barrier(1 + takeThreads.Length); Action addAction = () => { barierStart.SignalAndWait(); int index = 0; while ((index = Interlocked.Increment(ref addedElemCount)) <= elemCount) { sem.Release(); SpinWaitHelper.SpinWait(addSpin); } barierAdders.SignalAndWait(); }; Action takeAction = () => { CancellationToken myToken = srcCancel.Token; barierStart.SignalAndWait(); try { while (!srcCancel.IsCancellationRequested) { sem.Wait(myToken); SpinWaitHelper.SpinWait(takeSpin); } } catch (OperationCanceledException) { } while (sem.Wait(0)) { } barierTakers.SignalAndWait(); }; for (int i = 0; i < addThreads.Length; i++) { addThreads[i] = new Thread(new ThreadStart(addAction)); } for (int i = 0; i < takeThreads.Length; i++) { takeThreads[i] = new Thread(new ThreadStart(takeAction)); } for (int i = 0; i < takeThreads.Length; i++) { takeThreads[i].Start(); } for (int i = 0; i < addThreads.Length; i++) { addThreads[i].Start(); } barierStart.SignalAndWait(); Stopwatch sw = Stopwatch.StartNew(); barierAdders.SignalAndWait(); srcCancel.Cancel(); barierTakers.SignalAndWait(); sw.Stop(); for (int i = 0; i < addThreads.Length; i++) { addThreads[i].Join(); } for (int i = 0; i < takeThreads.Length; i++) { takeThreads[i].Join(); } Console.WriteLine(name + ". SemaphoreLight. Time = " + sw.ElapsedMilliseconds.ToString() + "ms"); return(sw.Elapsed); }