public async Task LocalMutualExclusion_NoDeadlock() { IScope <string> mutex = new LocalMutualExclusion <string>(EqualityComparer <string> .Default); using (await mutex.WithScopeAsync(KeyOne, CancellationToken.None)) using (await mutex.WithScopeAsync(KeyTwo, CancellationToken.None)) { } using (await mutex.WithScopeAsync(KeyTwo, CancellationToken.None)) using (await mutex.WithScopeAsync(KeyOne, CancellationToken.None)) { } using (await mutex.WithScopeAsync(KeyOne, CancellationToken.None)) using (await mutex.WithScopeAsync(KeyTwo, CancellationToken.None)) { } }
public async Task LocalMutualExclusion_Serializes() { IScope <string> mutex = new LocalMutualExclusion <string>(EqualityComparer <string> .Default); var taskOne = mutex.WithScopeAsync(KeyOne, CancellationToken.None); var taskTwo = mutex.WithScopeAsync(KeyTwo, CancellationToken.None); var taskWaiting = mutex.WithScopeAsync(KeyOne, CancellationToken.None); using (await taskOne) using (await taskTwo) { Assert.IsFalse(taskWaiting.IsCompleted); } using (await taskWaiting) { } }
public async Task LocalMutualExclusion_ReferenceCounts() { var local = new LocalMutualExclusion <string>(EqualityComparer <string> .Default); IScope <string> mutex = local; Action <string, int> AssertReferenceCount = (key, expected) => { int actual; Assert.IsTrue(local.TryGetReferenceCount(key, out actual)); Assert.AreEqual(expected, actual); }; var taskA = mutex.WithScopeAsync(KeyOne, CancellationToken.None); AssertReferenceCount(KeyOne, 1); var taskB = mutex.WithScopeAsync(KeyOne, CancellationToken.None); AssertReferenceCount(KeyOne, 2); using (await taskA) { AssertReferenceCount(KeyOne, 2); Assert.IsFalse(taskB.IsCompleted); } AssertReferenceCount(KeyOne, 1); using (await taskB) { AssertReferenceCount(KeyOne, 1); } int zero; Assert.IsFalse(local.TryGetReferenceCount(KeyOne, out zero), "did not clean up per-item semaphore resource"); }