public async Task AllBareLock_ExceptionInRelease_ThrowsUnlockException() { // setup var locks = new List <IBareAsyncLock <string> >(); var l = new Mock <IBareAsyncLock <string> >(MockBehavior.Strict); l.As <IBareAsyncLock>().Setup(x => x.BarelyLockAsync(It.IsAny <CancellationToken>())) .ReturnsAsync(() => { return("0"); }); l.Setup(x => x.BarelyUnlock()).Throws(new SynchronizationLockException()); locks.Add(l.Object); var guard = await MultiSync.AllAsync(locks); // act and assert var exception = Should.Throw <UnlockException>(() => guard.Dispose()); exception.PriorException.ShouldBeNull(); exception.InnerExceptions .ToDictionary(kv => kv.Key, kv => kv.Value.GetType()) .ShouldBe(new Dictionary <int, Type> { [0] = typeof(SynchronizationLockException) }); }
public void AllBareLockTimeout_Timeout_NotAcquire(TimingMethod timingMethod, int sleepMs) { // setup var locks = new List <IBareLock>(); object valueToken = null; { var l = new Mock <IBareLock>(MockBehavior.Strict); l.Setup(x => x.BarelyTryLock(1, out valueToken)).Returns(new TryLockTimeoutDelegate((int _, out object v) => { Thread.Sleep(sleepMs); v = new object(); return(true); })); l.Setup(x => x.BarelyUnlock()); locks.Add(l.Object); } { var l = new Mock <IBareLock>(MockBehavior.Strict); l.Setup(x => x.BarelyTryLock(out valueToken)).Returns(false); l.Setup(x => x.BarelyTryLock(0, out valueToken)).Returns(false); l.Setup(x => x.BarelyUnlock()); locks.Add(l.Object); } locks.Add(new Mock <IBareLock>(MockBehavior.Strict).Object); // prevent infinite loop // act var guard = MultiSync.All(locks, 1, timingMethod); // assert guard.ShouldBeNull(); }
public void UnorderedAcquisition() { using (var guard = MultiSync.All(new[] { lock1, lock2 })) { var list1 = guard.Value[0]; var list2 = guard.Value[1]; list1.AddRange(list2); } }
public async Task AllBareLock_Acquire(params int[][] initialLockStates) { // setup var remainingStates = initialLockStates.ToList(); var locks = new List <IBareAsyncLock>(); var currentStates = remainingStates.First().ToList(); remainingStates.RemoveAt(0); int count = currentStates.Count; for (int i = 0; i < count; ++i) { int iCopy = i; var l = new Mock <IBareAsyncLock>(MockBehavior.Strict); l.Setup(x => x.BarelyLockAsync(It.IsAny <CancellationToken>())).ReturnsAsync(() => { currentStates[iCopy].ShouldBe(0); ++currentStates[iCopy]; return(iCopy.ToString()); }); object valueToken; l.Setup(x => x.BarelyTryLock(out valueToken)).Returns(new TryLockDelegate((out object v) => { if (currentStates[iCopy] > 0) { // unlock "externally" --currentStates[iCopy]; var next = remainingStates.FirstOrDefault(); if (next != null) { remainingStates.RemoveAt(0); for (int s = 0; s < count; ++s) { currentStates[s] += next[s]; } } v = null; return(false); } ++currentStates[iCopy]; v = iCopy.ToString(); return(true); })); l.Setup(x => x.BarelyUnlock()).Callback(() => -- currentStates[iCopy]); locks.Add(l.Object); } // act var guard = await MultiSync.AllAsync(locks); // assert currentStates.ShouldBe(Enumerable.Repeat(1, count)); guard.Value.ShouldBe(Enumerable.Range(0, count).Select(x => x.ToString())); }
public void AllBareLock_ExceptionInAcquireAndRelease_ThrowsUnlockException() { // setup var locks = new List <IBareLock <string> >(); { var l = new Mock <IBareLock <string> >(MockBehavior.Strict); l.As <IBareLock>().Setup(x => x.BarelyLock()).Returns(() => { return("0"); }); l.Setup(x => x.BarelyUnlock()).Throws(new SynchronizationLockException()); locks.Add(l.Object); } { var l = new Mock <IBareLock <string> >(MockBehavior.Strict); l.As <IBareLock>().Setup(x => x.BarelyLock()).Returns(() => { return("1"); }); object valueToken; l.As <IBareLock>().Setup(x => x.BarelyTryLock(out valueToken)).Returns(new TryLockDelegate((out object v) => { v = "1"; return(true); })); l.Setup(x => x.BarelyUnlock()); locks.Add(l.Object); } var guard = MultiSync.All(locks); // act and assert var exception = Should.Throw <UnlockException>(() => guard.Dispose()); exception.PriorException.ShouldBeNull(); exception.InnerExceptions .ToDictionary(kv => kv.Key, kv => kv.Value.GetType()) .ShouldBe(new Dictionary <int, Type> { [0] = typeof(SynchronizationLockException) }); }
public async Task AllBareLock_Release() { // setup var locks = new List <IBareAsyncLock>(); var currentStates = new List <int> { 0, 0, 0 }; int count = currentStates.Count; for (int i = 0; i < count; ++i) { int iCopy = i; var l = new Mock <IBareAsyncLock>(MockBehavior.Strict); l.Setup(x => x.BarelyLockAsync(It.IsAny <CancellationToken>())).ReturnsAsync(() => { currentStates[iCopy].ShouldBe(0); ++currentStates[iCopy]; return(iCopy.ToString()); }); object valueToken; l.Setup(x => x.BarelyTryLock(out valueToken)).Returns(new TryLockDelegate((out object v) => { ++currentStates[iCopy]; v = iCopy.ToString(); return(true); })); l.Setup(x => x.BarelyUnlock()).Callback(() => -- currentStates[iCopy]); locks.Add(l.Object); } var guard = await MultiSync.AllAsync(locks); // act guard.Dispose(); // assert currentStates.ShouldBe(Enumerable.Repeat(0, count)); }
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 void Dining() { for (var method = (Method)0; method < Method.Count; ++method) { for (var nt = 2; nt <= 32; ++nt) { ForceGC(); var table = new List <IBareLock>(); var lockOrders = new Dictionary <IBareLock, int>(); for (var i = 0; i < nt; ++i) { table.Add(Synchronized.Create(new object())); lockOrders[table[i]] = i; } var diners = new List <Philosopher>(); for (var i = 0; i < nt; ++i) { int j = i; int k = j < nt - 1 ? j + 1 : 0; Action <IReadOnlyList <IBareLock>, Action> lockToEat = null; switch (method) { case Method.Ordered: lockToEat = (locks, eat) => { locks = locks.OrderBy(x => lockOrders[x]).ToList(); foreach (var l in locks) { l.BarelyLock(); } eat(); foreach (var l in locks) { l.BarelyUnlock(); } }; break; case Method.SmartAndPolite: lockToEat = (locks, eat) => { using (MultiSync.All(locks)) { eat(); } }; break; } diners.Add(new Philosopher(new[] { table[j], table[k] }, lockToEat)); } var threads = new List <Thread>(); var stopwatch = new Stopwatch(); for (var i = 0; i < nt; ++i) { threads.Add(new Thread(diners[i].Dine)); } stopwatch.Start(); for (var i = 0; i < nt; ++i) { threads[i].Start(); } foreach (var t in threads) { t.Join(); } 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 void AllBareLockTimeout_InfiniteTimeout_Acquire(TimingMethod timingMethod, int[][] lockStates) { AllBareLock_Acquire(lockStates, locks => MultiSync.All(locks, -1, timingMethod)); }
public void AllBareLock_Acquire(int[][] lockStates) { AllBareLock_Acquire(lockStates, locks => MultiSync.All(locks)); }
public void AllBareLockTimeout_MaxTimeout_Acquire(int timeoutMs, TimingMethod timingMethod) { AllBareLock_Acquire(new[] { new[] { 0, 0, 0 } }, locks => MultiSync.All(locks, timeoutMs, timingMethod)); }