public void WaitAsync_NotEmpty_CanCedeTurn() { using (var cts = new CancellationTokenSource()) using (var turnstile = new Turnstile()) { var t1 = turnstile.WaitAsync(); var t2 = turnstile.WaitAsync(cts.Token); var t3 = turnstile.WaitAsync(); Assert.That(turnstile.HasWaiting); TaskAssert.DoesNotEnd(t1); TaskAssert.DoesNotEnd(t2); TaskAssert.DoesNotEnd(t3); cts.Cancel(); Assert.That(turnstile.Turn()); TaskAssert.Completed(t1); TaskAssert.Cancelled(t2); TaskAssert.DoesNotEnd(t3); Assert.That(turnstile.Turn()); TaskAssert.Completed(t3); Assert.That(!turnstile.HasWaiting); Assert.That(!turnstile.Turn()); } }
public void WaitAsync_NotEmpty_WaitsForTurn() { using (var turnstile = new Turnstile()) { var t1 = turnstile.WaitAsync(); var t2 = turnstile.WaitAsync(); var t3 = turnstile.WaitAsync(); Assert.That(turnstile.HasWaiting); TaskAssert.DoesNotEnd(t1); TaskAssert.DoesNotEnd(t2); TaskAssert.DoesNotEnd(t3); Assert.That(turnstile.Turn()); TaskAssert.Completed(t1); TaskAssert.DoesNotEnd(t2); TaskAssert.DoesNotEnd(t3); Assert.That(turnstile.Turn()); TaskAssert.Completed(t2); TaskAssert.DoesNotEnd(t3); Assert.That(turnstile.Turn()); TaskAssert.Completed(t3); Assert.That(!turnstile.HasWaiting); Assert.That(!turnstile.Turn()); } }
/// <summary> /// Decrement the active count and increment the balance. /// </summary> void Release() { // Exit the section. var active = Interlocked.Decrement(ref FActive); Ensure.That(active >= 0, @"Multiple release."); // Increase the balance. if (Interlocked.Increment(ref FBalance) <= 0) { // Release the next reservation. FWaiting.Turn(); } }