/////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: Services\Tests\Calculator\ServiceExec.sg // // Note: A generic worker-style server implementation // using System; using System.Collections; using System.Threading; using Microsoft.SingSharp; using Microsoft.Singularity; using Microsoft.Singularity.Channels; using Microsoft.Singularity.Directory; using Microsoft.Singularity.ServiceManager; namespace Microsoft.Singularity.Services { // To inherit this class, what you need to do is: // 1) To call the base constructor in your constructor. // 2) To implement Accept and NewWorker methods. This class // automatically creates and assigns threads to Run method of your // worker object. public abstract class WorkerServiceExec : ServiceExec { protected IList serviceSignalList; public WorkerServiceExec([Claims]DirectoryServiceContract.Imp:Ready! ep, string! path) { base(ep, path); serviceSignalList = new ArrayList(); } /// /// Checks if the request channel type is acceptable. /// protected abstract bool Accept(ServiceContract.Exp:Start! ep); /// /// Create a new worker object for the specified channel. The worker /// created by this method is assigned to a thread by this class. /// protected abstract IRunnable NewWorker([Claims]ServiceContract.Exp:Start! ep); protected override bool Listen(ServiceProviderContract.Exp:Start! provider, ThreadTerminationContract.Exp:Start! signal) { bool result = true; Thread worker; switch receive { case provider.Connect(serviceEp): { if (Accept(serviceEp)) { worker = CreateWorker(serviceEp); if (worker == null) { provider.SendNackConnect(null); } else { provider.SendAckConnect(); worker.Start(); } } else { provider.SendNackConnect(serviceEp); } break; } case provider.ChannelClosed(): { TerminateWorkers(); result = false; break; } case signal.Stop(): { TerminateWorkers(); signal.SendAckStop(); result = false; break; } case signal.ChannelClosed(): { TerminateWorkers(); result = false; break; } } return result; } protected Thread CreateWorker([Claims]ServiceContract.Exp:Start! ep) { IRunnable worker; CPTestContract.Exp:Start! server; ThreadTerminationContract.Imp! imp; ThreadTerminationContract.Exp! exp; worker = NewWorker(ep); if (worker == null) { return null; } ThreadTerminationContract.NewChannel(out imp, out exp); worker.Signal(exp); lock (this) { serviceSignalList.Add(new TRef(imp)); } return new Thread(new ThreadStart(worker.Run)); } private void TerminateWorkers() { TRef signalRef; ThreadTerminationContract.Imp:Start signal; lock (this) { foreach (Object obj in serviceSignalList) { if (obj != null) { signalRef = obj as TRef; if (signalRef != null) { signal = signalRef.Acquire(); signal.SendStop(); switch receive { case signal.AckStop(): break; case signal.ChannelClosed(): break; } signalRef.Release(signal); } } } serviceSignalList.Clear(); } } } }