// ---------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // ---------------------------------------------------------------------------- namespace Microsoft.Singularity.Security { using System; using System.Collections; using System.Threading; using Microsoft.SingSharp; using Microsoft.Contracts; using Microsoft.Singularity.Channels; using Microsoft.Singularity.Directory; /// /// A ChannelPool maintains a pool of open channels. /// (to the security service). It should be possible to parameterize this /// class for general use. /// internal class ChannelPool { #if POOLED const int POOL_CAPACITY = 10; #else const int POOL_CAPACITY = 1; #endif /// /// The unused channels /// TRef[]! trefs; int capacity = POOL_CAPACITY; int nalloc = 0; int navail = 0; /// /// Synchronization token /// object token; bool disposed; public ChannelPool() { int i; trefs = new TRef[capacity]; token = new object(); disposed = false; } // opens a connection to the security service private static SecurityDiagnosticsContract.Imp OpenChannel() { SecurityDiagnosticsContract.Imp! imp; SecurityDiagnosticsContract.Exp! exp; SecurityDiagnosticsContract.NewChannel(out imp, out exp); // open a channel to the nameservice DirectoryServiceContract.Imp ns = DirectoryService.NewClientEndpoint(); // try to bind ns.SendBind(Bitter.FromString2(SecurityDiagnosticsContract.ModuleName), exp); switch receive { case ns.AckBind(): break; case ns.NakBind(rejected, error): delete imp; delete rejected; delete ns; return null; } delete ns; imp.RecvReady(); return imp; } /// /// Returns a free channel. Blocks if none is available. /// public SecurityDiagnosticsContract.Imp! Acquire() { lock (token) { // wait if no channel is available while (true) { if (navail != 0) { navail--; return ((!)trefs[navail]).Acquire(); } if (nalloc < capacity) { SecurityDiagnosticsContract.Imp imp = OpenChannel(); if (imp != null) { trefs[nalloc] = new TRef (imp); return ((!)trefs[nalloc++]).Acquire(); } } Monitor.Wait(token); } } } /// /// Releases a channel /// public void Release([Claims]SecurityDiagnosticsContract.Imp! imp) { lock (token) { ((!)trefs[navail++]).Release(imp); Monitor.PulseAll(token); } } /// /// Closes the channels /// public void Dispose() { lock (token) { if (!disposed) { int i; for (i = 0; i < navail; i++) { SecurityDiagnosticsContract.Imp! imp = ((!)trefs[i]).Acquire(); delete imp; } disposed = true; } } } } }