singrdk/base/Applications/Tests/MonitorTest/PulseAllTest.cs

177 lines
5.2 KiB
C#
Raw Permalink Normal View History

2008-03-05 09:52:00 -05:00
///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Note:
//
using System;
using System.Threading;
2008-11-17 18:29:00 -05:00
using Microsoft.Singularity;
2008-03-05 09:52:00 -05:00
using Microsoft.Singularity.UnitTest;
namespace Microsoft.Singularity.Applications
{
/// <remarks>
/// A test of Monitor.PulseAll. A collection of threads waits on
/// a single monitor for a pulse all.
/// </remarks>
2008-11-17 18:29:00 -05:00
[TestClass]
public class PulseAllTest : TestClass
{
[TestMethod]
public void FewThreadsTest()
{
(new Pulser(8, 2, Expect)).RunTest();
}
[TestMethod]
public void ManyThreadsTest()
{
(new Pulser(50, 2, Expect)).RunTest();
}
}
internal sealed class Pulser
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
TestLog Expect;
2008-03-05 09:52:00 -05:00
int waiterCount = 50;
int timeoutSeconds = 2;
int passedBarrier = 0;
bool waiterRunning = false;
volatile bool timedOut = false;
volatile bool stop = false;
volatile int generation = 0;
ManualResetEvent! controllerReady = new ManualResetEvent(false);
ManualResetEvent! finishedEvent = new ManualResetEvent(false);
AutoResetEvent! barrierEvent = new AutoResetEvent(false);
object! monitor = new object();
bool []! visited;
2008-11-17 18:29:00 -05:00
public Pulser(int threadCount, int timeoutSeconds, TestLog expect)
{
this.waiterCount = threadCount;
this.visited = new bool [threadCount];
this.timeoutSeconds = timeoutSeconds;
this.Expect = expect;
}
2008-03-05 09:52:00 -05:00
private static void Yield()
{
#if SINGULARITY
Thread.Yield();
#else
Thread.Sleep(0);
#endif
}
public void WatchdogThreadMain()
{
2008-11-17 18:29:00 -05:00
TimeSpan delta = TimeSpan.FromMilliseconds(500);
2008-03-05 09:52:00 -05:00
int now = this.generation;
int last = 0;
do {
last = now;
if (finishedEvent.WaitOne(delta)) {
return;
}
Yield();
now = this.generation;
2008-11-17 18:29:00 -05:00
Expect.NotEqual(last, now, "progress was made in the last cycle");
} while (true);
2008-03-05 09:52:00 -05:00
}
public void ControllerThreadMain()
{
const int iterations = 1000;
2008-11-17 18:29:00 -05:00
const int YieldFudge = 150;
2008-03-05 09:52:00 -05:00
// Signal worker threads to start
controllerReady.Set();
Yield();
for (int i = 1; i <= iterations; i++) {
barrierEvent.WaitOne();
lock (this.monitor) {
// Reset check state
this.passedBarrier = 0;
for (int j = 0; j < visited.Length; j++) {
visited[j] = false;
}
// Set stop flag if end is reached
this.stop = (i == iterations);
// Wake up waiters
Monitor.PulseAll(this.monitor);
}
}
finishedEvent.Set();
}
public void WaiterThreadMain()
{
while (!stop) {
Monitor.Enter(this.monitor);
try {
2008-11-17 18:29:00 -05:00
Expect.False(waiterRunning, "Only one waiter is in the monitor");
2008-03-05 09:52:00 -05:00
waiterRunning = true;
2008-11-17 18:29:00 -05:00
Expect.False(this.visited[this.passedBarrier],
"Thread is before the barrier");
2008-03-05 09:52:00 -05:00
this.visited[this.passedBarrier] = true;
this.passedBarrier++;
this.generation++;
2008-11-17 18:29:00 -05:00
Expect.LessOrEqual(this.passedBarrier, waiterCount,
"Not too many waiters passed the barrier");
2008-03-05 09:52:00 -05:00
if (this.passedBarrier == this.waiterCount) {
barrierEvent.Set();
}
this.waiterRunning = false;
Monitor.Wait(this.monitor);
this.waiterRunning = true;
}
finally {
this.waiterRunning = false;
Monitor.Exit(this.monitor);
}
}
}
public void RunTest()
{
Thread watchdog =
new Thread(new ThreadStart(WatchdogThreadMain));
Thread controller =
new Thread(new ThreadStart(ControllerThreadMain));
watchdog.Start();
controller.Start();
controllerReady.WaitOne();
for (int i = 0; i < waiterCount; i++) {
Thread t = new Thread(new ThreadStart(WaiterThreadMain));
t.Start();
}
while (!controller.Join(TimeSpan.FromMilliseconds(100))) {
2008-11-17 18:29:00 -05:00
Expect.False(this.timedOut, "Completed before timeout");
2008-03-05 09:52:00 -05:00
}
watchdog.Join();
}
}
}