Browse Source

2003-02-05 Patrik Torstensson

	* ThreadPool.cs: Reformated and fixed issue that made all thread exit the pool.

svn path=/trunk/mcs/; revision=11239
Patrik Torstensson 23 years ago
parent
commit
14c8194db3

+ 4 - 0
mcs/class/corlib/System.Threading/ChangeLog

@@ -1,3 +1,7 @@
+2003-02-05  Patrik Torstensson
+
+	* ThreadPool.cs: Reformated and fixed issue that made all thread exit the pool. 
+
 2003-02-04  Lluis Sanchez Gual <[email protected]>
 
 	* ThreadPool.cs: Implemented RegisterWaitForSingleObject methods.

+ 162 - 157
mcs/class/corlib/System.Threading/ThreadPool.cs

@@ -2,7 +2,7 @@
 // System.Threading.ThreadPool
 //
 // Author:
-//   Patrik Torstensson ([email protected])
+//   Patrik Torstensson
 //   Dick Porter ([email protected])
 //
 // (C) Ximian, Inc.  http://www.ximian.com
@@ -11,61 +11,60 @@
 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);
+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());
+			_Threads = ArrayList.Synchronized(new ArrayList());
 
-         // Holds requests..
-         _RequestQueue = Queue.Synchronized(new Queue(128));
+			// 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;
+			_MaxThreads = 16;
+			_CurrentThreads = 0;
+			_RequestInQueue = 0;
+			_ThreadsInUse = 0;
+			_ThreadCreateTriggerRequests = 5;
 
 			// TODO: This temp starts one thread, remove this..
 			CheckIfStartThread();
@@ -73,59 +72,63 @@ namespace System.Threading
 			// 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();
-      }
+			//_MonitorThread = new Thread(new ThreadStart(MonitorThread));
+			//_MonitorThread.Start();
+		}
 
-      internal void RemoveThread() {
-         Interlocked.Decrement(ref _CurrentThreads);
-         _Threads.Remove(Thread.CurrentThread);
-      }
+		internal void RemoveThread() {
+			Interlocked.Decrement(ref _CurrentThreads);
+			_Threads.Remove(Thread.CurrentThread);
+		}
 
-      internal void CheckIfStartThread() {
-         bool bCreateThread = false;
+		internal void CheckIfStartThread() {
+			bool bCreateThread = false;
 
-         if (_CurrentThreads == 0) {
-            bCreateThread = true;
-         }
+			if (_CurrentThreads == 0) {
+				bCreateThread = true;
+			}
 
 			if ((	_MaxThreads == -1 || _CurrentThreads < _MaxThreads) && 
-					_ThreadsInUse > 0 && 
-					_RequestInQueue >= _ThreadCreateTriggerRequests) {
-            bCreateThread = true;
-         }
+				_ThreadsInUse > 0 && 
+				_RequestInQueue >= _ThreadCreateTriggerRequests) {
+				bCreateThread = true;
+			}
 
-         if (bCreateThread) {
-            Interlocked.Increment(ref _CurrentThreads);
+			if (bCreateThread) {
+				Interlocked.Increment(ref _CurrentThreads);
       
-            Thread Start = new Thread(new ThreadStart(WorkerThread));
-            Start.IsThreadPoolThreadInternal = true;
-            Start.Start();
+				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)) {
-                  // timeout
-                  RemoveThread();
-                  return;
-               }
-            }
+				_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);
 
@@ -133,77 +136,79 @@ namespace System.Threading
 				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);
-            }
-         }
-      }
+					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);
+			}
+		}
 		
-		/* This is not used currently 
-      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) {
+			return QueueUserWorkItem(callback, null);
+		}
 
-      internal bool QueueUserWorkItemInternal(WaitCallback callback, object context) {
-         ThreadPoolWorkItem Item = new ThreadPoolWorkItem();
+		internal bool QueueUserWorkItemInternal(WaitCallback callback, object context) {
+			ThreadPoolWorkItem Item = new ThreadPoolWorkItem();
 
-         Item._CallBack = callback;
-         Item._Context = context;
+			Item._CallBack = callback;
+			Item._Context = context;
 
-         AddItem(ref Item);
+			AddItem(ref Item);
 
-         // LAMESPEC: Return value? should use exception here if anything goes wrong
-         return true;
-      }
+			// 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 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);
+			return _Threadpool.QueueUserWorkItemInternal(callback);
 		}
 
 		public static bool QueueUserWorkItem(WaitCallback callback, object state) {
-         return _Threadpool.QueueUserWorkItemInternal(callback, state);
+			return _Threadpool.QueueUserWorkItemInternal(callback, state);
 		}
 
-      public static bool UnsafeQueueUserWorkItem(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) {
@@ -229,29 +234,29 @@ namespace System.Threading
 			return waiter;
 		}
 
-      [CLSCompliant(false)]
+		[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);
-	  }
+			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();
-      }
+			throw new NotImplementedException();
+		}
 
 		[MonoTODO]
 		public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, long millisecondsTimeOutInterval, bool executeOnlyOnce) {
-         throw new NotImplementedException();
+			throw new NotImplementedException();
 		}
 
 		[MonoTODO]
 		public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, TimeSpan timeout, bool executeOnlyOnce) {
-         throw new NotImplementedException();
-      }
+			throw new NotImplementedException();
+		}
 
 		[CLSCompliant(false)][MonoTODO]
 		public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callback, object state, uint millisecondsTimeOutInterval, bool executeOnlyOnce) {
-         throw new NotImplementedException();
-      }
+			throw new NotImplementedException();
+		}
 	}
 }