/////////////////////////////////////////////////////////////////////////////// // // 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))] namespace Microsoft.Singularity.Applications { [ConsoleCategory(HelpMessage="Showcase thread synchronization with Mutex/Waithandle", DefaultAction=true)] internal class Parameters { [InputEndpoint("data")] public readonly TRef Stdin; [OutputEndpoint("data")] public readonly TRef Stdout; [LongParameter( "t", Default=2, HelpMessage="Number of Waiters (threads)")] internal long numberOfWaiters; [BoolParameter( "d", Default=false, HelpMessage="Debug Mode")] internal bool debugMode; 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; private static bool debugMode; private class WaiterThread { private uint myIndex; public WaiterThread(uint index) { myIndex = index; } public void Go() { String myName = names[myIndex]; Write(String.Format("Enter Thread {0}\n", myName)); Write(String.Format(" {0}: signaling auto-reset event\n", myName)); ((AutoResetEvent!)waiters[myIndex]).Set(); for (uint Loop = 0; Loop < 5; Loop++) { Write(String.Format(" {0}: waiting for mutex\n", myName)); mutex.WaitOne(); Write(String.Format(" {0}: got mutex\n", myName)); Thread.Sleep(1000); Write(String.Format(" {0}: releasing mutex\n", myName)); mutex.ReleaseMutex(); Thread.Yield(); } // // Tell other waiters we're done. // Write(String.Format(" {0}: signaling manual-reset event\n", myName)); ((ManualResetEvent!)others[myIndex]).Set(); // // Wait for other waiter. // Write(String.Format(" {0}: waiting for other waiters\n", myName)); foreach (WaitHandle! other in others) { other.WaitOne(); } Write(String.Format(" {0}: heard from other waiters\n", myName)); Write(String.Format("Exit Thread {0}\n", myName)); } } public static void Usage() { Console.WriteLine("\nUsage: godot [NumberOfWaitThreads]\n\n"); } internal static int AppMain(Parameters! config) { uint numberOfWaiters = (uint) config.numberOfWaiters; debugMode = config.debugMode; Write(String.Format("\nStarting wait test with {0} wait threads\n\n", numberOfWaiters)); 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); } Write("Created synchronization primitives\n\n"); // // 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. // Write("Waiting for all waiters to start\n"); foreach (WaitHandle! waiter in waiters) { waiter.WaitOne(); } // // Release the Mutex to the wolves. // Write("About to release mutex\n"); mutex.ReleaseMutex(); Write("Mutex released\n"); // // Wait for the threads to die. // #if false #if NOT_YET Write("Waiting for all waiters to terminate\n"); for (uint Loop = 0; Loop < numberOfWaiters; Loop++) { threads[Loop].Join(); } #else Write("Waiting for 30 sec while threads play\n"); Thread.Sleep(30000); #endif #endif Write("Goodbye\n"); return 0; } private static void Write(string s) { string msg = "Godot:" + s; Console.Write(msg); if (debugMode) { DebugStub.Write(msg); } } } }