singrdk/base/Applications/cassini/Singularity/CassiniThreadPool.sg

117 lines
3.7 KiB
Plaintext
Raw Normal View History

2008-03-05 09:52:00 -05:00
///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: CassiniThreadPool.sg
//
// Note: adapted from FatThreadPool.sg
//
#if THREAD_POOL
using System.Collections;
using System.Threading;
namespace Microsoft.VisualStudio.WebHost
{
/// <remarks>This class implements a non-Singleton
/// threadpool and has a configurable work queue
/// size. </remarks>
internal sealed class CassiniThreadPool
{
object monitor;
Queue commands; // Queue of ThreadStart
int queuedItems;
readonly int maxQueuedItems;
volatile int threadCount;
volatile bool shutdown;
ManualResetEvent shutdownEvent;
[Microsoft.Contracts.NotDelayed]
internal CassiniThreadPool(int maxThreads, int maxQueuedItems)
requires maxThreads > 0;
requires maxQueuedItems > 0;
requires maxThreads <= maxQueuedItems;
{
this.monitor = new object();
this.commands = new Queue();
this.queuedItems = 0;
this.maxQueuedItems = maxQueuedItems;
this.threadCount = maxThreads;
this.shutdown = false;
this.shutdownEvent = new ManualResetEvent(false);
for (int i = 0; i < maxThreads; i++) {
Thread t = new Thread(new ThreadStart(WorkerMain));
t.Start();
}
}
/// <summary> Queues call to constructor supplied
/// delegate with user supplied object. This method
/// blocks if maximum queue size is reached. </summary>
internal void QueueUserWorkItem(ThreadStart! command)
{
Monitor.Enter(this.monitor);
while (this.queuedItems == this.maxQueuedItems) {
Monitor.Wait(this.monitor);
}
commands.Enqueue(command);
this.queuedItems++;
Monitor.Pulse(this.monitor);
Monitor.Exit(this.monitor);
}
private void WorkerMain()
{
while (true) {
ThreadStart command;
lock (this.monitor) {
while (queuedItems == 0 && !shutdown) {
Monitor.Wait(this.monitor);
}
if (queuedItems == 0 && shutdown) {
break;
}
command = (ThreadStart) (commands.Dequeue());
assert(command != null);
if (this.queuedItems-- == this.maxQueuedItems) {
Monitor.Pulse(this.monitor);
}
}
command();
}
lock (this.monitor) {
if (--this.threadCount == 0) {
shutdownEvent.Set();
}
}
}
/// <summary>
/// Shutdown thread pool instance. Caller blocks until
/// the threads in the pool have finished outstanding
/// work items.
/// </summary>
internal void Shutdown()
{
lock (this.monitor) {
shutdown = true;
Monitor.PulseAll(this.monitor);
}
shutdownEvent.WaitOne();
Microsoft.Singularity.DebugStub.Assert(commands.Count == 0);
}
}
}
#endif // THREAD_POOL