public void ShouldRunModulesAtCorrectTickRate() { LosgapSystem.InvokeOnMaster(() => { const int MODULE_EXEC_LENGTH = 1; const int MODULE_BLOCK_SIZE = 1; const int MODULE_TICK_RATE_MS = 10; const int TEST_ERROR_MARGIN_NUM_TICKS = 5; ILosgapModule[] inputExecutionUnits = { new MockModule(MODULE_BLOCK_SIZE, MODULE_TICK_RATE_MS), }; PipelineProcessor processor = new PipelineProcessor(inputExecutionUnits); // Set up context ((MockModule)inputExecutionUnits[0]).SetExecutionRange(MODULE_EXEC_LENGTH); Task.Run(() => { Thread.Sleep(1000); processor.Dispose(); }); // Execute processor.Start(); // Assert outcome Assert.IsTrue(((MockModule)inputExecutionUnits[0]).PostExecuteCalls <= MODULE_TICK_RATE_MS + TEST_ERROR_MARGIN_NUM_TICKS); }); }
public void TestDispose() { MasterSlaveBarrier testBarrier = new MasterSlaveBarrier(2U); Thread slaveA = new Thread(testBarrier.SlaveWaitForFirstOpen); Thread slaveB = new Thread(testBarrier.SlaveWaitForFirstOpen); slaveA.Start(); LosgapSystem.InvokeOnMaster(() => testBarrier.Dispose()); slaveB.Start(); slaveA.Join(); slaveB.Join(); testBarrier = new MasterSlaveBarrier(2U); slaveA = new Thread(() => { testBarrier.SlaveWaitForFirstOpen(); testBarrier.SlaveWaitForReset(); }); slaveB = new Thread(() => { testBarrier.SlaveWaitForFirstOpen(); testBarrier.SlaveWaitForReset(); }); slaveA.Start(); slaveB.Start(); LosgapSystem.InvokeOnMaster(() => { testBarrier.MasterOpenBarrier(); testBarrier.MasterWaitForClose(); testBarrier.Dispose(); }); slaveA.Join(); slaveB.Join(); }
public void PMIShouldNotStallPipeline() { LosgapSystem.InvokeOnMaster(() => { // Define variables and constants const int MODULE_EXEC_LENGTH = 15; const int MODULE_BLOCK_SIZE = 1; const int MODULE_TICK_RATE_MS = 10; ILosgapModule[] inputExecutionUnits = { new MockModule(MODULE_BLOCK_SIZE, MODULE_TICK_RATE_MS), }; PipelineProcessor processor = new PipelineProcessor(inputExecutionUnits); // Set up context ((MockModule)inputExecutionUnits[0]).SetExecutionRange(MODULE_EXEC_LENGTH); ((MockModule)inputExecutionUnits[0]).ExecBlock += () => { Thread.Sleep(15); processor.InvokeOnMaster(new PipelineMasterInvocation(() => Thread.Sleep(15), true)); }; ((MockModule)inputExecutionUnits[0]).PostExec += processor.Dispose; // Execute processor.Start(); // Assert outcome }); }
public void SingleModuleSingleIterationTest() { LosgapSystem.InvokeOnMaster(() => { // Must invoke on master because the PP has assurances that the master thread is invoking operations // Define variables and constants const int MODULE_EXEC_LENGTH = 500021; const int MODULE_BLOCK_SIZE = 200; ILosgapModule[] inputExecutionUnits = { new MockModule(MODULE_BLOCK_SIZE, Int32.MaxValue), }; ParallelizationProvider pp = new ParallelizationProvider(); // Set up context ((MockModule)inputExecutionUnits[0]).SetExecutionRange(MODULE_EXEC_LENGTH); ((MockModule)inputExecutionUnits[0]).PostExec += () => { int[] workspace = ((MockModule)inputExecutionUnits[0]).Workspace; for (int i = 0; i < MODULE_EXEC_LENGTH; ++i) { Assert.AreEqual(i, workspace[i]); } ((IDisposable)pp).Dispose(); }; // Execute inputExecutionUnits[0].PipelineIterate(pp, 0L); // Assert outcome }); }
public void TestForceSingleThreaded() { LosgapSystem.InvokeOnMaster(() => { // Must invoke on master because the PP has assurances that the master thread is invoking operations const int NUM_ITERATIONS = 10000; HashSet <Thread> invokedThreads = new HashSet <Thread>(); ParallelizationProvider pp = new ParallelizationProvider(); for (int i = 0; i < NUM_ITERATIONS; i++) { pp.ForceSingleThreadedMode = true; invokedThreads.Clear(); pp.InvokeOnAll(() => { lock (invokedThreads) { invokedThreads.Add(Thread.CurrentThread); } }, true); Assert.AreEqual(LosgapSystem.MasterThread, invokedThreads.Single()); invokedThreads.Clear(); pp.Execute(100, 1, atomic => { lock (invokedThreads) { invokedThreads.Add(Thread.CurrentThread); } }); Assert.AreEqual(LosgapSystem.MasterThread, invokedThreads.Single()); pp.ForceSingleThreadedMode = false; } }); }
public void TestInvokeOnAll() { LosgapSystem.InvokeOnMaster(() => { // Must invoke on master because the PP has assurances that the master thread is invoking operations // Define variables and constants const int NUM_ITERATIONS = 10000; HashSet <Thread> invokedThreads = new HashSet <Thread>(); ParallelizationProvider pp = new ParallelizationProvider(); // Set up context // Execute for (int i = 0; i < NUM_ITERATIONS; i++) { invokedThreads.Clear(); pp.InvokeOnAll(() => { lock (invokedThreads) { invokedThreads.Add(Thread.CurrentThread); } }, true); Assert.AreEqual(pp.NumThreads, (uint)invokedThreads.Count); invokedThreads.Clear(); pp.InvokeOnAll(() => { lock (invokedThreads) { invokedThreads.Add(Thread.CurrentThread); } }, false); Assert.AreEqual(pp.NumThreads - 1U, (uint)invokedThreads.Count); Assert.IsFalse(invokedThreads.Contains(Thread.CurrentThread)); } // Assert outcome }); }
public void MasterWaitOnExternalLock(object lockObj, Func <bool> completionPredicate) { Assure.NotNull(lockObj); Assure.NotNull(completionPredicate); Assure.True(Monitor.IsEntered(lockObj)); Assure.Equal(Thread.CurrentThread, LosgapSystem.MasterThread); Monitor.Enter(externalLockObjLock); externalLockObj = lockObj; try { while (!completionPredicate()) { while (masterInvocationQueue.Count > 0) { PipelineMasterInvocation pmi; if (!masterInvocationQueue.TryDequeue(out pmi)) { continue; } try { if (pmi.IsSynchronousCall) { Monitor.Enter(pmi.InvocationCompleteMonitor); pmi.Action(); } else { pmi.Action(); } } catch (Exception e) { if (pmi.IsSynchronousCall) { pmi.RaisedException = e; } else { LosgapSystem.ExitWithError("Exception raised in asynchronous pipeline master invocation.", e); } } finally { if (pmi.IsSynchronousCall) { Monitor.Pulse(pmi.InvocationCompleteMonitor); Monitor.Exit(pmi.InvocationCompleteMonitor); } } } Monitor.Exit(externalLockObjLock); Monitor.Wait(lockObj); Monitor.Enter(externalLockObjLock); } } finally { externalLockObj = null; Monitor.Exit(externalLockObjLock); } }
public static void ShutdownTests() { bool exited = false; LosgapSystem.SystemExited += () => exited = true; LosgapSystem.Exit(); SpinWait.SpinUntil(() => exited); if (((TestLoggingProvider)Logger.LoggingProvider).SuppressionActive) { LosgapSystem.ExitWithError("Logging provider was still suppressed at test finish."); } }
private static void MasterLoop() { try { LosgapSystem.AddModule(typeof(RenderingModule)); LosgapSystem.Start(); } catch (ThreadAbortException) { Thread.ResetAbort(); } catch (Exception e) { Logger.Fatal("Test master loop has failed.", e); } }
public void MultipleModuleMultipleIterationTest() { LosgapSystem.InvokeOnMaster(() => { // Must invoke on master because the PP has assurances that the master thread is invoking operations // Define variables and constants const int NUM_ITERATIONS = 500; int[] moduleExecLengths = { 136, 88433, 287, 1 }; int[] moduleBlockSizes = { 313, 5000, 2, 1000 }; ILosgapModule[] inputExecutionUnits = moduleBlockSizes.Select(mbs => new MockModule(mbs, Int32.MaxValue)).ToArray(); for (int i = 0; i < moduleExecLengths.Length; i++) { ((MockModule)inputExecutionUnits[i]).SetExecutionRange(moduleExecLengths[i]); } ParallelizationProvider pp = new ParallelizationProvider(); // Set up context // Execute for (int i = 0; i < NUM_ITERATIONS; i++) { foreach (ILosgapModule module in inputExecutionUnits) { module.PipelineIterate(pp, 0L); } } // Assert outcome for (int i = 0; i < inputExecutionUnits.Length; i++) { MockModule executionUnit = (MockModule)inputExecutionUnits[i]; Assert.IsTrue(executionUnit.PostExecuteCalls == NUM_ITERATIONS); int[] workspace = executionUnit.Workspace; for (int w = 0; w < workspace.Length; ++w) { Assert.AreEqual(executionUnit.PostExecuteCalls * w, workspace[w]); } } }); }
public void MasterWaitForClose() { Assure.Equal(Thread.CurrentThread, LosgapSystem.MasterThread); Monitor.Enter(barrierOpenLock); hydrateInvocationQueue: while (masterInvocationQueue.Count > 0) { PipelineMasterInvocation pmi; if (!masterInvocationQueue.TryDequeue(out pmi)) { continue; } try { if (pmi.IsSynchronousCall) { Monitor.Enter(pmi.InvocationCompleteMonitor); pmi.Action(); } else { pmi.Action(); } } catch (Exception e) { if (pmi.IsSynchronousCall) { pmi.RaisedException = e; } else { LosgapSystem.ExitWithError("Exception raised in asynchronous pipeline master invocation.", e); } } finally { if (pmi.IsSynchronousCall) { Monitor.Pulse(pmi.InvocationCompleteMonitor); Monitor.Exit(pmi.InvocationCompleteMonitor); } } } if (barrierOpen) { Monitor.Wait(barrierOpenLock); goto hydrateInvocationQueue; } Monitor.Exit(barrierOpenLock); }
public void TestOpenAndClose() { MasterSlaveBarrier testBarrier = new MasterSlaveBarrier(2U); Thread slaveA = new Thread(testBarrier.SlaveWaitForFirstOpen); slaveA.Start(); Thread slaveB = new Thread(testBarrier.SlaveWaitForFirstOpen); slaveB.Start(); Assert.IsFalse(slaveA.Join(TimeSpan.FromSeconds(0.5d))); Assert.IsFalse(slaveB.Join(TimeSpan.FromSeconds(0.5d))); LosgapSystem.InvokeOnMaster(testBarrier.MasterOpenBarrier); slaveA.Join(); slaveB.Join(); slaveA = new Thread(testBarrier.SlaveWaitForReset); slaveA.Start(); slaveB = new Thread(testBarrier.SlaveWaitForReset); bool barrierClosed = false; object barrierClosePulse = new object(); LosgapSystem.InvokeOnMasterAsync(() => { testBarrier.MasterWaitForClose(); testBarrier.MasterOpenBarrier(); lock (barrierClosePulse) { barrierClosed = true; Monitor.Pulse(barrierClosePulse); } }); Thread.Sleep(TimeSpan.FromSeconds(0.5d)); Assert.IsFalse(barrierClosed); Monitor.Enter(barrierClosePulse); slaveB.Start(); slaveA.Join(); slaveB.Join(); Monitor.Wait(barrierClosePulse); Monitor.Exit(barrierClosePulse); Assert.IsTrue(barrierClosed); testBarrier.Dispose(); }
private void StartSlave() { try { WorkBarrier.SlaveWaitForFirstOpen(); while (!isDisposed) { if (currentWorkIsInvokeAllAction) { currentInvokeAllAction(); } else { for (int blockIndex = Interlocked.Decrement(ref numReservableBlocks); blockIndex >= 0; blockIndex = Interlocked.Decrement(ref numReservableBlocks)) { int blockStartInc = currentBlockSize * blockIndex; int blockEndEx = currentBlockSize * (blockIndex + 1); for (int i = blockStartInc; i < blockEndEx; ++i) { currentAction(i); } } } WorkBarrier.SlaveWaitForReset(); } Monitor.Enter(slaveThreadExitMonitor); if (--numSlavesStillRunning == 0) { Monitor.Pulse(slaveThreadExitMonitor); } Monitor.Exit(slaveThreadExitMonitor); Logger.Debug("Slave thread " + Thread.CurrentThread.Name + " has exited normally."); } catch (ThreadAbortException) { Thread.ResetAbort(); } catch (Exception e) { LosgapSystem.ExitWithError("Slave thread encounted an unhandled exception.", e); } }
public void TestWaitForSlavesToExit() { LosgapSystem.InvokeOnMaster(() => { // Must invoke on master because the PP has assurances that the master thread is invoking operations const int NUM_ITERATIONS = 300; for (int i = 0; i < NUM_ITERATIONS; ++i) { ParallelizationProvider pp = new ParallelizationProvider(); pp.Execute(10, 1, x => { if (x > 10) { Console.WriteLine("This will never be called."); } }); (pp as IDisposable).Dispose(); pp.WaitForSlavesToExit(); } }); }
public void InvokeOnMaster(PipelineMasterInvocation pmi) { if (isDisposed) { throw new ObjectDisposedException("Can not invoke actions on master when pipeline is disposed!"); } if (Thread.CurrentThread == LosgapSystem.MasterThread) { try { pmi.Action(); } catch (Exception e) { if (pmi.IsSynchronousCall) { pmi.RaisedException = e; } else { LosgapSystem.ExitWithError("Exception raised in asynchronous pipeline master invocation.", e); } } } else { if (pmi.IsSynchronousCall) { Monitor.Enter(pmi.InvocationCompleteMonitor); ParallelizationProvider.SlaveQueueOnMaster(pmi); Monitor.Wait(pmi.InvocationCompleteMonitor); Monitor.Exit(pmi.InvocationCompleteMonitor); } else { ParallelizationProvider.SlaveQueueOnMaster(pmi); } } }