111 lines
2.8 KiB
C#
111 lines
2.8 KiB
C#
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// File: WatchDogTimer.cs
|
|
//
|
|
// Note:
|
|
//
|
|
|
|
using System;
|
|
using System.Threading;
|
|
|
|
namespace Microsoft.Singularity.UnitTest
|
|
{
|
|
/// <remarks> A class to watch for timeouts.</remarks>
|
|
public sealed class WatchDogTimer
|
|
{
|
|
private TimeSpan timeout;
|
|
private Thread worker;
|
|
private volatile bool running;
|
|
private AutoResetEvent! workEvent;
|
|
|
|
public WatchDogTimer(TimeSpan timeout)
|
|
{
|
|
this.timeout = timeout;
|
|
this.running = false;
|
|
this.workEvent = new AutoResetEvent(false);
|
|
}
|
|
|
|
public void Start()
|
|
{
|
|
lock (this) {
|
|
if (!this.running) {
|
|
this.running = true;
|
|
this.worker = new Thread(new ThreadStart(WorkerMain));
|
|
this.worker.Start();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Stop()
|
|
{
|
|
Thread toJoin = null;
|
|
lock (this) {
|
|
if (this.running) {
|
|
this.running = false;
|
|
this.workEvent.Set();
|
|
toJoin = this.worker;
|
|
this.worker = null;
|
|
}
|
|
}
|
|
if (toJoin != null) {
|
|
toJoin.Join();
|
|
}
|
|
}
|
|
|
|
public void Defer()
|
|
{
|
|
lock (this) {
|
|
Assert.True(this.running,
|
|
"Watch dog timer expired or stopped.");
|
|
workEvent.Set();
|
|
}
|
|
}
|
|
|
|
public bool Running
|
|
{
|
|
get { return this.running; }
|
|
}
|
|
|
|
private void LockedWorkerExpire()
|
|
{
|
|
try {
|
|
Assert.True(false, "Watch-dog timed out.");
|
|
}
|
|
catch (FailedAssertionException) {
|
|
// Expected
|
|
}
|
|
this.running = false;
|
|
}
|
|
|
|
private void WorkerMain()
|
|
{
|
|
bool done = false;
|
|
while (!done) {
|
|
bool signalled = WaitOne(this.workEvent, this.timeout);
|
|
lock (this) {
|
|
if (signalled) {
|
|
done = !this.running;
|
|
}
|
|
else {
|
|
LockedWorkerExpire();
|
|
done = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static bool WaitOne(WaitHandle /*!*/ w, TimeSpan t)
|
|
{
|
|
#if SINGULARITY
|
|
return w.WaitOne(t);
|
|
#else
|
|
return w.WaitOne(t, false);
|
|
#endif
|
|
}
|
|
}
|
|
}
|