public void CancelLockAsync_Cancel() { // setup var semaphore = new SemaphoreSlim(1); var value = new List(); var subject = new AsyncSynchronized <List>(semaphore, value); // act and assert Should.Throw <TaskCanceledException>(() => subject.LockAsync(new CancellationTokenSource(0).Token)); }
public void CancelWithLockAsyncAction_Cancel() { // setup var semaphore = new SemaphoreSlim(1); var value = new List(); var subject = new AsyncSynchronized <List>(semaphore, value); // act and assert Should.Throw <TaskCanceledException>(() => subject.WithLockAsync((v) => Task.FromResult(0), new CancellationTokenSource(0).Token)); semaphore.CurrentCount.ShouldBe(1); }
public async Task BarelyLockAsync_Acquire() { // setup var semaphore = new SemaphoreSlim(1); var value = new List(); var subject = new AsyncSynchronized <List>(semaphore, value); // act and assert var result = await subject.BarelyLockAsync(); semaphore.CurrentCount.ShouldBe(0); result.ShouldBe(value); }
public void WithLockAsyncFunc_Exception_Release() { // setup var semaphore = new SemaphoreSlim(1); var value = new List(); var subject = new AsyncSynchronized <List>(semaphore, value); // act and assert Should.Throw <CustomException>(() => subject.WithLockAsync(new Func <List, int>((v) => { throw new CustomException(); }))); semaphore.CurrentCount.ShouldBe(1); }
public void WithLockAction_ExceptionInAcquire_ThrowLockException() { // setup var semaphore = new SemaphoreSlim(1); var value = new List(); var subject = new AsyncSynchronized <List>(semaphore, value); semaphore.Dispose(); // act and assert var exception = Should.Throw <LockException>(() => subject.WithLock((v) => { })); exception.InnerException.ShouldBeOfType <ObjectDisposedException>(); }
public async Task LockAsync_Acquire() { // setup var semaphore = new SemaphoreSlim(1); var value = new List(); var subject = new AsyncSynchronized <List>(semaphore, value); // act and assert using (var guard = await subject.LockAsync()) { semaphore.CurrentCount.ShouldBe(0); guard.Value.ShouldBe(value); } semaphore.CurrentCount.ShouldBe(1); }
public async Task WithLockAsyncAction_Acquire() { // setup var semaphore = new SemaphoreSlim(1); var value = new List(); var subject = new AsyncSynchronized <List>(semaphore, value); // act and assert await subject.WithLockAsync((v) => { semaphore.CurrentCount.ShouldBe(0); v.ShouldBe(value); }); semaphore.CurrentCount.ShouldBe(1); }
public void WithLockAction_ExceptionInRelease_ThrowUnlockException() { // setup var semaphore = new SemaphoreSlim(1); var value = new List(); var subject = new AsyncSynchronized <List>(semaphore, value); // act and assert var exception = Should.Throw <UnlockException>(() => subject.WithLock((v) => { semaphore.Dispose(); })); exception.PriorException.ShouldBeNull(); exception.InnerExceptions .ToDictionary(kv => kv.Key, kv => kv.Value.GetType()) .ShouldBe(new Dictionary <int, Type> { [0] = typeof(ObjectDisposedException) }); }
private async Task DiningAsync() { for (var method = (Method)0; method < Method.Count; ++method) { for (var nt = 2; nt <= 32; ++nt) { ForceGC(); var table = new List <IBareAsyncLock>(); var lockOrders = new Dictionary <IBareAsyncLock, int>(); for (var i = 0; i < nt; ++i) { table.Add(AsyncSynchronized.Create(new object())); lockOrders[table[i]] = i; } var diners = new List <AsyncPhilosopher>(); for (var i = 0; i < nt; ++i) { int j = i; int k = j < nt - 1 ? j + 1 : 0; Func <IReadOnlyList <IBareAsyncLock>, Action, Task> lockToEat = null; switch (method) { case Method.Ordered: lockToEat = async(locks, eat) => { locks = locks.OrderBy(x => lockOrders[x]).ToList(); foreach (var l in locks) { await l.BarelyLockAsync().ConfigureAwait(false); } eat(); foreach (var l in locks) { l.BarelyUnlock(); } }; break; case Method.SmartAndPolite: lockToEat = async(locks, eat) => { using (await MultiSync.AllAsync(locks).ConfigureAwait(false)) { eat(); } }; break; } diners.Add(new AsyncPhilosopher(new[] { table[j], table[k] }, lockToEat)); } var stopwatch = new Stopwatch(); var tasks = new List <Task>(); stopwatch.Start(); for (var i = 0; i < nt; ++i) { tasks.Add(Task.Run(diners[i].DineAsync)); } await Task.WhenAll(tasks).ConfigureAwait(false); stopwatch.Stop(); Console.WriteLine($"{method},{nt},{stopwatch.Elapsed.TotalSeconds}"); } } }
private async Task TestSynchronizeMultipleAsync(int repeat, bool output) { var watch = new Stopwatch(); var x1 = new X(); var x2 = new X(); var sqrt = (int)Math.Sqrt(1); ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { lock (x1) { lock (x2) { x1.Value += sqrt; x2.Value += sqrt; } } } watch.Stop(); if (output) { Console.WriteLine($"lock,{((double)watch.ElapsedTicks * 100 / repeat)}"); } var syncMonitor1 = Synchronized.Create(x1); var syncMonitor2 = Synchronized.Create(x2); ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { using (var v1 = syncMonitor1.Lock()) using (var v2 = syncMonitor2.Lock()) { v1.Value.Value += sqrt; v2.Value.Value += sqrt; } } watch.Stop(); if (output) { Console.WriteLine($"Synchronized.Lock,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { using (var guard = MultiSync.All(new[] { syncMonitor1, syncMonitor2 })) { guard.Value[0].Value += sqrt; guard.Value[1].Value += sqrt; } } watch.Stop(); if (output) { Console.WriteLine($"MultiSync.All Monitor,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); var syncMonitors = new[] { syncMonitor1, syncMonitor2 }; watch.Restart(); for (int i = 0; i < repeat; ++i) { using (var guard = MultiSync.All(syncMonitors)) { guard.Value[0].Value += sqrt; guard.Value[1].Value += sqrt; } } watch.Stop(); if (output) { Console.WriteLine($"MultiSync.All Monitor reusing array,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); watch.Restart(); var semaphore1 = new SemaphoreSlim(1); var semaphore2 = new SemaphoreSlim(1); for (int i = 0; i < repeat; ++i) { await semaphore1.WaitAsync().ConfigureAwait(false); await semaphore2.WaitAsync().ConfigureAwait(false); x1.Value += sqrt; x2.Value += sqrt; semaphore2.Release(); semaphore1.Release(); } watch.Stop(); if (output) { Console.WriteLine($"SemaphoreSlim.WaitAsync,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); var syncSemaphore1 = AsyncSynchronized.Create(x1); var syncSemaphore2 = AsyncSynchronized.Create(x2); watch.Restart(); for (int i = 0; i < repeat; ++i) { using (var guard = await MultiSync.AllAsync(new[] { syncSemaphore1, syncSemaphore2 }).ConfigureAwait(false)) { guard.Value[0].Value += sqrt; guard.Value[1].Value += sqrt; } } watch.Stop(); if (output) { Console.WriteLine($"MultiSync.AllAsync SemaphoreSlim,{((double)watch.ElapsedTicks * 100 / repeat)}"); } }
public async Task TestSynchronizedAsync(int repeat, bool output) { var watch = new Stopwatch(); var x = new X(); var sqrt = (int)Math.Sqrt(1); ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { lock (x) { x.Value += sqrt; } } watch.Stop(); if (output) { Console.WriteLine($"lock,{((double)watch.ElapsedTicks * 100 / repeat)}"); } var syncMonitor = Synchronized.Create(x); ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { syncMonitor.WithLock((v) => v.Value += sqrt); } watch.Stop(); if (output) { Console.WriteLine($"Synchronized.WithLock,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { using (var guard = syncMonitor.Lock()) { guard.Value.Value += sqrt; } } watch.Stop(); if (output) { Console.WriteLine($"Synchronized.Lock,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); var semaphore = new SemaphoreSlim(1); watch.Restart(); for (int i = 0; i < repeat; ++i) { semaphore.Wait(); x.Value += sqrt; semaphore.Release(); } watch.Stop(); if (output) { Console.WriteLine($"SemaphoreSlim.Wait,{((double)watch.ElapsedTicks * 100 / repeat)}"); } var syncSemaphore = AsyncSynchronized.Create(x); ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { syncSemaphore.WithLock((v) => v.Value += sqrt); } watch.Stop(); if (output) { Console.WriteLine($"AsyncSynchronized.WithLock,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { using (var guard = syncSemaphore.Lock()) { guard.Value.Value += sqrt; } } watch.Stop(); if (output) { Console.WriteLine($"AsyncSynchronized.Lock,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { await semaphore.WaitAsync().ConfigureAwait(false); x.Value += sqrt; semaphore.Release(); } watch.Stop(); if (output) { Console.WriteLine($"SemaphoreSlim.WaitAsync,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { await syncSemaphore.WithLockAsync((v) => v.Value += sqrt).ConfigureAwait(false); } watch.Stop(); if (output) { Console.WriteLine($"AsyncSynchronized.WithLockAsync,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { using (var guard = await syncSemaphore.LockAsync().ConfigureAwait(false)) { guard.Value.Value += sqrt; } } watch.Stop(); if (output) { Console.WriteLine($"AsyncSynchronized.LockAsync,{((double)watch.ElapsedTicks * 100 / repeat)}"); } }