2008-03-05 09:52:00 -05:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Microsoft Research Singularity
|
|
|
|
//
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
//
|
|
|
|
// Note: Singularity wait primitives test program.
|
|
|
|
//
|
|
|
|
using Microsoft.Singularity.V1.Services;
|
|
|
|
using Microsoft.Singularity.V1.Threads;
|
|
|
|
using System;
|
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
using System.Threading;
|
|
|
|
|
|
|
|
|
|
|
|
using Microsoft.Contracts;
|
|
|
|
using Microsoft.SingSharp.Reflection;
|
|
|
|
using Microsoft.Singularity.Applications;
|
|
|
|
using Microsoft.Singularity.Channels;
|
|
|
|
using Microsoft.Singularity.Io;
|
|
|
|
using Microsoft.Singularity.Configuration;
|
|
|
|
[assembly: Transform(typeof(ApplicationResourceTransform))]
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
namespace Microsoft.Singularity.Applications
|
|
|
|
{
|
|
|
|
[ConsoleCategory(HelpMessage="Showcase thread synchronization with Mutex/Waithandle", DefaultAction=true)]
|
2008-03-05 09:52:00 -05:00
|
|
|
internal class Parameters {
|
|
|
|
[InputEndpoint("data")]
|
|
|
|
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
|
|
|
|
|
|
|
|
[OutputEndpoint("data")]
|
|
|
|
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
|
|
|
|
|
|
|
|
[LongParameter( "t", Default=2, HelpMessage="Number of Waiters (threads)")]
|
|
|
|
internal long numberOfWaiters;
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
[BoolParameter( "d", Default=false, HelpMessage="Debug Mode")]
|
|
|
|
internal bool debugMode;
|
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
reflective internal Parameters();
|
|
|
|
|
|
|
|
internal int AppMain() {
|
|
|
|
return Godot.AppMain(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public class Godot
|
|
|
|
{
|
|
|
|
private static Mutex! mutex;
|
|
|
|
private static WaitHandle[]! waiters;
|
|
|
|
private static WaitHandle[]! others;
|
|
|
|
private static String[]! names;
|
|
|
|
private static WaiterThread[] threadDetails;
|
|
|
|
private static Thread[] threads;
|
2008-11-17 18:29:00 -05:00
|
|
|
private static bool debugMode;
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
private class WaiterThread {
|
|
|
|
private uint myIndex;
|
|
|
|
|
|
|
|
public WaiterThread(uint index) {
|
|
|
|
myIndex = index;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Go()
|
|
|
|
{
|
|
|
|
String myName = names[myIndex];
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
Write(String.Format("Enter Thread {0}\n", myName));
|
2008-03-05 09:52:00 -05:00
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
Write(String.Format(" {0}: signaling auto-reset event\n", myName));
|
2008-03-05 09:52:00 -05:00
|
|
|
((AutoResetEvent!)waiters[myIndex]).Set();
|
|
|
|
|
|
|
|
for (uint Loop = 0; Loop < 5; Loop++) {
|
2008-11-17 18:29:00 -05:00
|
|
|
Write(String.Format(" {0}: waiting for mutex\n", myName));
|
2008-03-05 09:52:00 -05:00
|
|
|
mutex.WaitOne();
|
2008-11-17 18:29:00 -05:00
|
|
|
Write(String.Format(" {0}: got mutex\n", myName));
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
Thread.Sleep(1000);
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
Write(String.Format(" {0}: releasing mutex\n", myName));
|
2008-03-05 09:52:00 -05:00
|
|
|
mutex.ReleaseMutex();
|
|
|
|
Thread.Yield();
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Tell other waiters we're done.
|
|
|
|
//
|
2008-11-17 18:29:00 -05:00
|
|
|
Write(String.Format(" {0}: signaling manual-reset event\n", myName));
|
2008-03-05 09:52:00 -05:00
|
|
|
((ManualResetEvent!)others[myIndex]).Set();
|
|
|
|
|
|
|
|
//
|
|
|
|
// Wait for other waiter.
|
|
|
|
//
|
2008-11-17 18:29:00 -05:00
|
|
|
Write(String.Format(" {0}: waiting for other waiters\n", myName));
|
2008-03-05 09:52:00 -05:00
|
|
|
foreach (WaitHandle! other in others) {
|
|
|
|
other.WaitOne();
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
Write(String.Format(" {0}: heard from other waiters\n", myName));
|
2008-03-05 09:52:00 -05:00
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
Write(String.Format("Exit Thread {0}\n", myName));
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void Usage()
|
|
|
|
{
|
|
|
|
Console.WriteLine("\nUsage: godot [NumberOfWaitThreads]\n\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
internal static int AppMain(Parameters! config)
|
|
|
|
{
|
|
|
|
uint numberOfWaiters = (uint) config.numberOfWaiters;
|
2008-11-17 18:29:00 -05:00
|
|
|
debugMode = config.debugMode;
|
2008-03-05 09:52:00 -05:00
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
Write(String.Format("\nStarting wait test with {0} wait threads\n\n",
|
|
|
|
numberOfWaiters));
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
names = new String[4];
|
|
|
|
names[0] = "Estragon";
|
|
|
|
names[1] = "Vladimir";
|
|
|
|
names[2] = "Lucky";
|
|
|
|
names[3] = "Pozzo";
|
|
|
|
|
|
|
|
//
|
|
|
|
// Create some synchronization primitives to test.
|
|
|
|
//
|
|
|
|
mutex = new Mutex(true);
|
|
|
|
waiters = new WaitHandle[numberOfWaiters];
|
|
|
|
others = new WaitHandle[numberOfWaiters];
|
|
|
|
for (uint Loop = 0; Loop < numberOfWaiters; Loop++) {
|
|
|
|
waiters[Loop] = new AutoResetEvent(false);
|
|
|
|
others[Loop] = new ManualResetEvent(false);
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
Write("Created synchronization primitives\n\n");
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
//
|
|
|
|
// Fire up the waiters.
|
|
|
|
//
|
|
|
|
threads = new Thread[numberOfWaiters];
|
|
|
|
threadDetails = new WaiterThread[numberOfWaiters];
|
|
|
|
for (uint Loop = 0; Loop < numberOfWaiters; Loop++) {
|
|
|
|
threadDetails[Loop] = new WaiterThread(Loop);
|
|
|
|
threads[Loop] = new Thread(
|
|
|
|
new ThreadStart(threadDetails[Loop].Go));
|
|
|
|
((!)threads[Loop]).Start();
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Wait for the waiters to tell us they're about to start waiting.
|
|
|
|
//
|
2008-11-17 18:29:00 -05:00
|
|
|
Write("Waiting for all waiters to start\n");
|
2008-03-05 09:52:00 -05:00
|
|
|
foreach (WaitHandle! waiter in waiters) {
|
|
|
|
waiter.WaitOne();
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Release the Mutex to the wolves.
|
|
|
|
//
|
2008-11-17 18:29:00 -05:00
|
|
|
Write("About to release mutex\n");
|
2008-03-05 09:52:00 -05:00
|
|
|
mutex.ReleaseMutex();
|
2008-11-17 18:29:00 -05:00
|
|
|
Write("Mutex released\n");
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
//
|
|
|
|
// Wait for the threads to die.
|
|
|
|
//
|
|
|
|
#if false
|
|
|
|
#if NOT_YET
|
2008-11-17 18:29:00 -05:00
|
|
|
Write("Waiting for all waiters to terminate\n");
|
2008-03-05 09:52:00 -05:00
|
|
|
for (uint Loop = 0; Loop < numberOfWaiters; Loop++) {
|
|
|
|
threads[Loop].Join();
|
|
|
|
}
|
|
|
|
#else
|
2008-11-17 18:29:00 -05:00
|
|
|
Write("Waiting for 30 sec while threads play\n");
|
2008-03-05 09:52:00 -05:00
|
|
|
Thread.Sleep(30000);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
Write("Goodbye\n");
|
2008-03-05 09:52:00 -05:00
|
|
|
return 0;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
|
|
|
|
private static void Write(string s)
|
|
|
|
{
|
|
|
|
string msg = "Godot:" + s;
|
|
|
|
Console.Write(msg);
|
|
|
|
if (debugMode) {
|
|
|
|
DebugStub.Write(msg);
|
|
|
|
}
|
|
|
|
}
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
}
|