2 // System.Threading.ThreadPool
5 // Patrik Torstensson (patrik.torstensson@labs2.com)
6 // Dick Porter (dick@ximian.com)
8 // (C) Ximian, Inc. http://www.ximian.com
9 // (C) Patrik Torstensson
12 using System.Collections;
14 namespace System.Threading
16 /// <summary> (Patrik T notes)
17 /// This threadpool is focused on saving resources not giving max performance.
19 /// Note, this class is not perfect but it works. ;-) Should also replace
20 /// the queue with an internal one (performance)
22 /// This class should also use a specialized queue to increase performance..
25 public sealed class ThreadPool {
26 internal struct ThreadPoolWorkItem {
27 public WaitCallback _CallBack;
28 public object _Context;
31 private int _ThreadTimeout;
33 private long _MaxThreads;
34 private long _CurrentThreads;
35 private long _ThreadsInUse;
36 private long _RequestInQueue;
37 private long _ThreadCreateTriggerRequests;
39 private Thread _MonitorThread;
40 private Queue _RequestQueue;
42 private ArrayList _Threads;
43 private ManualResetEvent _DataInQueue;
45 static ThreadPool _Threadpool;
48 _Threadpool = new ThreadPool();
51 private ThreadPool() {
52 // 30 sec timeout default
53 _ThreadTimeout = 30 * 1000;
55 // Used to signal that there is data in the queue
56 _DataInQueue = new ManualResetEvent(false);
58 _Threads = ArrayList.Synchronized(new ArrayList());
61 _RequestQueue = Queue.Synchronized(new Queue(128));
67 _ThreadCreateTriggerRequests = 5;
69 // Keeps track of requests in the queue and inreases the number of threads if neededs
70 _MonitorThread = new Thread(new ThreadStart(MonitorThread));
71 _MonitorThread.Start();
74 internal void RemoveThread() {
75 Interlocked.Decrement(ref _CurrentThreads);
76 _Threads.Remove(Thread.CurrentThread);
79 internal void CheckIfStartThread() {
80 bool bCreateThread = false;
82 if (_CurrentThreads == 0) {
86 if ((_MaxThreads == -1 || _CurrentThreads < _MaxThreads) && _ThreadsInUse > 0 && _RequestInQueue > _ThreadCreateTriggerRequests) {
91 Interlocked.Increment(ref _CurrentThreads);
93 Thread Start = new Thread(new ThreadStart(WorkerThread));
95 Start.IsThreadPoolThreadInternal = true;
101 internal void AddItem(ref ThreadPoolWorkItem Item) {
102 CheckIfStartThread();
104 if (Interlocked.Increment(ref _RequestInQueue) == 1) {
108 _RequestQueue.Enqueue(Item);
111 // Work Thread main function
112 internal void WorkerThread() {
113 bool bWaitForData = true;
117 if (!_DataInQueue.WaitOne(_ThreadTimeout, false)) {
124 Interlocked.Increment(ref _ThreadsInUse);
127 ThreadPoolWorkItem oItem = (ThreadPoolWorkItem) _RequestQueue.Dequeue();
129 if (Interlocked.Decrement(ref _RequestInQueue) == 0) {
130 _DataInQueue.Reset();
133 oItem._CallBack(oItem._Context);
135 catch (InvalidOperationException) {
139 catch (ThreadAbortException) {
140 // We will leave here.. (thread abort can't be handled)
144 Interlocked.Decrement(ref _ThreadsInUse);
149 internal void MonitorThread() {
153 CheckIfStartThread();
157 internal bool QueueUserWorkItemInternal(WaitCallback callback) {
158 return QueueUserWorkItem(callback, null);
161 internal bool QueueUserWorkItemInternal(WaitCallback callback, object context) {
162 ThreadPoolWorkItem Item = new ThreadPoolWorkItem();
164 Item._CallBack = callback;
165 Item._Context = context;
169 // LAMESPEC: Return value? should use exception here if anything goes wrong
173 public static bool BindHandle(IntPtr osHandle) {
174 throw new NotSupportedException("This is a win32 specific method, not supported Mono");
177 public static bool QueueUserWorkItem(WaitCallback callback) {
178 return _Threadpool.QueueUserWorkItemInternal(callback);
181 public static bool QueueUserWorkItem(WaitCallback callback, object state) {
182 return _Threadpool.QueueUserWorkItemInternal(callback, state);
185 public static bool UnsafeQueueUserWorkItem(WaitCallback callback, object state) {
186 return _Threadpool.QueueUserWorkItemInternal(callback, state);
190 public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, int millisecondsTimeOutInterval, bool executeOnlyOnce) {
191 if (millisecondsTimeOutInterval < -1) {
192 throw new ArgumentOutOfRangeException("timeout < -1");
195 throw new NotImplementedException();
199 public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, long millisecondsTimeOutInterval, bool executeOnlyOnce) {
200 if (millisecondsTimeOutInterval < -1) {
201 throw new ArgumentOutOfRangeException("timeout < -1");
204 throw new NotImplementedException();
208 public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, TimeSpan timeout, bool executeOnlyOnce) {
209 // LAMESPEC: I assume it means "timeout" when it says "millisecondsTimeOutInterval"
210 if (timeout.Milliseconds < -1) {
211 throw new ArgumentOutOfRangeException("timeout < -1");
213 if (timeout.Milliseconds > Int32.MaxValue) {
214 throw new NotSupportedException("timeout too large");
217 throw new NotImplementedException();
220 [CLSCompliant(false)][MonoTODO]
221 public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, uint millisecondsTimeOutInterval, bool executeOnlyOnce) {
222 throw new NotImplementedException();
226 public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, int millisecondsTimeOutInterval, bool executeOnlyOnce) {
227 throw new NotImplementedException();
231 public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, long millisecondsTimeOutInterval, bool executeOnlyOnce) {
232 throw new NotImplementedException();
236 public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, TimeSpan timeout, bool executeOnlyOnce) {
237 throw new NotImplementedException();
240 [CLSCompliant(false)][MonoTODO]
241 public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, uint millisecondsTimeOutInterval, bool executeOnlyOnce) {
242 throw new NotImplementedException();