| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- //
- // System.Threading.ThreadPool
- //
- // Author:
- // Patrik Torstensson
- // Dick Porter ([email protected])
- //
- // (C) Ximian, Inc. http://www.ximian.com
- // (C) Patrik Torstensson
- //
- using System;
- using System.Collections;
- namespace System.Threading {
- /// <summary> (Patrik T notes)
- /// This threadpool is focused on saving resources not giving max performance.
- ///
- /// Note, this class is not perfect but it works. ;-) Should also replace
- /// the queue with an internal one (performance)
- ///
- /// This class should also use a specialized queue to increase performance..
- /// </summary>
- ///
- public sealed class ThreadPool {
- internal struct ThreadPoolWorkItem {
- public WaitCallback _CallBack;
- public object _Context;
- }
- private int _ThreadTimeout;
- private long _MaxThreads;
- private long _CurrentThreads;
- private long _ThreadsInUse;
- private long _RequestInQueue;
- private long _ThreadCreateTriggerRequests;
- private Thread _MonitorThread;
- private Queue _RequestQueue;
- private ArrayList _Threads;
- private ManualResetEvent _DataInQueue;
- static ThreadPool _Threadpool;
- static ThreadPool() {
- _Threadpool = new ThreadPool();
- }
- private ThreadPool() {
- // 30 sec timeout default
- _ThreadTimeout = 30 * 1000;
- // Used to signal that there is data in the queue
- _DataInQueue = new ManualResetEvent(false);
-
- _Threads = ArrayList.Synchronized(new ArrayList());
- // Holds requests..
- _RequestQueue = Queue.Synchronized(new Queue(128));
- // TODO: This should be 2 x number of CPU:s in the box
- _MaxThreads = 16;
- _CurrentThreads = 0;
- _RequestInQueue = 0;
- _ThreadsInUse = 0;
- _ThreadCreateTriggerRequests = 5;
- // TODO: This temp starts one thread, remove this..
- CheckIfStartThread();
- // Keeps track of requests in the queue and increases the number of threads if needed
- // PT: Disabled - causes problems during shutdown
- //_MonitorThread = new Thread(new ThreadStart(MonitorThread));
- //_MonitorThread.Start();
- }
- internal void RemoveThread() {
- Interlocked.Decrement(ref _CurrentThreads);
- _Threads.Remove(Thread.CurrentThread);
- }
- internal void CheckIfStartThread() {
- bool bCreateThread = false;
- if (_CurrentThreads == 0) {
- bCreateThread = true;
- }
- if (( _MaxThreads == -1 || _CurrentThreads < _MaxThreads) &&
- _ThreadsInUse > 0 &&
- _RequestInQueue >= _ThreadCreateTriggerRequests) {
- bCreateThread = true;
- }
- if (bCreateThread) {
- Interlocked.Increment(ref _CurrentThreads);
-
- Thread Start = new Thread(new ThreadStart(WorkerThread));
- Start.IsThreadPoolThreadInternal = true;
- Start.IsBackground = true;
- Start.Start();
-
- _Threads.Add(Start);
- }
- }
- internal void AddItem(ref ThreadPoolWorkItem Item) {
- if (Interlocked.Increment(ref _RequestInQueue) == 1) {
- _DataInQueue.Set();
- }
- _RequestQueue.Enqueue(Item);
- }
- // Work Thread main function
- internal void WorkerThread() {
- bool bWaitForData = true;
- while (true) {
- if (bWaitForData) {
- if (!_DataInQueue.WaitOne(_ThreadTimeout, false)) {
- // Keep one thread running
- if (_CurrentThreads > 1) {
- // timeout
- RemoveThread();
- return;
- }
- }
- }
- Interlocked.Increment(ref _ThreadsInUse);
- // TODO: Remove when we know how to stop the watch thread
- CheckIfStartThread();
- try {
- ThreadPoolWorkItem oItem = (ThreadPoolWorkItem) _RequestQueue.Dequeue();
- if (Interlocked.Decrement(ref _RequestInQueue) == 0) {
- _DataInQueue.Reset();
- }
- oItem._CallBack(oItem._Context);
- }
- catch (InvalidOperationException) {
- // Queue empty
- bWaitForData = true;
- }
- catch (ThreadAbortException) {
- // We will leave here.. (thread abort can't be handled)
- RemoveThread();
- }
- finally {
- Interlocked.Decrement(ref _ThreadsInUse);
- }
- }
- }
-
- /* This is currently not in use
-
- internal void MonitorThread() {
- while (true) {
- if (_DataInQueue.WaitOne ()) {
- CheckIfStartThread();
- }
- Thread.Sleep(500);
- }
- }
-
- */
- internal bool QueueUserWorkItemInternal(WaitCallback callback) {
- return QueueUserWorkItem(callback, null);
- }
- internal bool QueueUserWorkItemInternal(WaitCallback callback, object context) {
- ThreadPoolWorkItem Item = new ThreadPoolWorkItem();
- Item._CallBack = callback;
- Item._Context = context;
- AddItem(ref Item);
- // LAMESPEC: Return value? should use exception here if anything goes wrong
- return true;
- }
- public static bool BindHandle(IntPtr osHandle) {
- throw new NotSupportedException("This is a win32 specific method, not supported Mono");
- }
- public static bool QueueUserWorkItem(WaitCallback callback) {
- return _Threadpool.QueueUserWorkItemInternal(callback);
- }
- public static bool QueueUserWorkItem(WaitCallback callback, object state) {
- return _Threadpool.QueueUserWorkItemInternal(callback, state);
- }
- public static bool UnsafeQueueUserWorkItem(WaitCallback callback, object state) {
- return _Threadpool.QueueUserWorkItemInternal(callback, state);
- }
- public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, int millisecondsTimeOutInterval, bool executeOnlyOnce) {
- if (millisecondsTimeOutInterval < -1) {
- throw new ArgumentOutOfRangeException("timeout < -1");
- }
- return RegisterWaitForSingleObject (waitObject, callback, state, TimeSpan.FromMilliseconds (Convert.ToDouble(millisecondsTimeOutInterval)), executeOnlyOnce);
- }
- public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, long millisecondsTimeOutInterval, bool executeOnlyOnce) {
- if (millisecondsTimeOutInterval < -1) {
- throw new ArgumentOutOfRangeException("timeout < -1");
- }
-
- return RegisterWaitForSingleObject (waitObject, callback, state, TimeSpan.FromMilliseconds (Convert.ToDouble(millisecondsTimeOutInterval)), executeOnlyOnce);
- }
- public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, TimeSpan timeout, bool executeOnlyOnce) {
- // LAMESPEC: I assume it means "timeout" when it says "millisecondsTimeOutInterval"
- int ms=Convert.ToInt32(timeout.TotalMilliseconds);
-
- if (ms < -1) {
- throw new ArgumentOutOfRangeException("timeout < -1");
- }
- if (ms > Int32.MaxValue) {
- throw new NotSupportedException("timeout too large");
- }
- RegisteredWaitHandle waiter = new RegisteredWaitHandle (waitObject, callback, state, timeout, executeOnlyOnce);
- _Threadpool.QueueUserWorkItemInternal (new WaitCallback(waiter.Wait), null);
- return waiter;
- }
- [CLSCompliant(false)]
- public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, uint millisecondsTimeOutInterval, bool executeOnlyOnce) {
- return RegisterWaitForSingleObject (waitObject, callback, state, TimeSpan.FromMilliseconds (Convert.ToDouble(millisecondsTimeOutInterval)), executeOnlyOnce);
- }
- [MonoTODO]
- public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, int millisecondsTimeOutInterval, bool executeOnlyOnce) {
- throw new NotImplementedException();
- }
- [MonoTODO]
- public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, long millisecondsTimeOutInterval, bool executeOnlyOnce) {
- throw new NotImplementedException();
- }
- [MonoTODO]
- public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, TimeSpan timeout, bool executeOnlyOnce) {
- throw new NotImplementedException();
- }
- [CLSCompliant(false)][MonoTODO]
- public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, uint millisecondsTimeOutInterval, bool executeOnlyOnce) {
- throw new NotImplementedException();
- }
- }
- }
|