public void WaitDoesNotThrowTheSecondTimeForAGivenThread() { var l = new TrackedLock(Locks, "A"); l.BlockingEnter(); var exc = new Exception[1]; var secondTimeSignal = new AutoResetEvent(false); var waiterThread = new Thread( () => { try { l.BlockingEnter(); l.Exit(); secondTimeSignal.WaitOne(); l.BlockingEnter(); l.Exit(); } catch (Exception e) { exc[0] = e; } } ); waiterThread.Priority = ThreadPriority.Highest; waiterThread.Start(); while ( (l.WaitingThreadCount == 0) && (waiterThread.ThreadState != ThreadState.Stopped) && (waiterThread.ThreadState != ThreadState.Aborted) ) { Thread.Sleep(1); } l.Exit(); l.BlockingEnter(); secondTimeSignal.Set(); while ( (l.WaitingThreadCount == 0) && (waiterThread.ThreadState != ThreadState.Stopped) && (waiterThread.ThreadState != ThreadState.Aborted) ) { Thread.Sleep(1); } l.Exit(); waiterThread.Join(); if (exc[0] != null) { throw new Exception("Worker thread failed", exc[0]); } }
public void WaitThrowsIfSimpleDeadlockWouldHaveOccurred() { var lA = new TrackedLock(Locks, "A"); var lB = new TrackedLock(Locks, "B"); lA.BlockingEnter(); var threadStartedSignal = new AutoResetEvent(false); var bOwnerThread = new Thread( () => { lB.BlockingEnter(); threadStartedSignal.Set(); lA.BlockingEnter(); } ); bOwnerThread.Priority = ThreadPriority.Highest; bOwnerThread.Name = "B Owner"; bOwnerThread.Start(); threadStartedSignal.WaitOne(); while (lA.WaitingThreadCount == 0) { Thread.Sleep(1); } Assert.Throws <DeadlockAvertedException>(() => lB.BlockingEnter()); lA.Exit(); bOwnerThread.Join(); }
public void WaitThrowsIfAlreadyHeld() { var l = new TrackedLock(Locks, "A"); l.BlockingEnter(); Assert.Throws <LockAlreadyHeldException>(() => l.BlockingEnter()); l.Exit(); }
public void WaitBlocksUntilReleased() { var log = new List <string>(); var l = new TrackedLock(Locks, "A"); lock (log) log.Add("Main+TryEnter"); Assert.IsTrue(l.TryEnter().Success); lock (log) log.Add("Main-TryEnter"); var threadStartedSignal = new AutoResetEvent(false); var waiterThread = new Thread( () => { threadStartedSignal.Set(); lock (log) log.Add("Waiter+Enter"); l.BlockingEnter(); lock (log) log.Add("Waiter-Enter"); l.Exit(); } ); waiterThread.Priority = ThreadPriority.Highest; waiterThread.Name = "Waiter"; waiterThread.Start(); threadStartedSignal.WaitOne(); // FIXME: There's a race here since WaitingThreadCount actually increases // slightly before the thread begins waiting. Bleh. while (l.WaitingThreadCount == 0) { Thread.Sleep(1); } lock (log) log.Add("Main+Exit"); l.Exit(); lock (log) log.Add("Main-Exit"); waiterThread.Join(); Assert.Less(log.IndexOf("Waiter+Enter"), log.IndexOf("Main+Exit")); Assert.Greater(log.IndexOf("Waiter-Enter"), log.IndexOf("Main-Exit")); }