# Patch created by root
# Date: Tue Jun  1 11:50:27 MDT 2004
# Repository: pnetlib
# Comments:
# Preventing ThreadPool from creating 16 completion threads just because it can. Added code to check for the number of threads needed, and just making sure that a minimum number of threads are started to support the completion thread queue.
#### End of Preamble ####

#### Patch data follows ####
Index: runtime/System/Threading/ThreadPool.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/runtime/System/Threading/ThreadPool.cs,v
retrieving revision 1.7
diff -c -r1.7 ThreadPool.cs
*** runtime/System/Threading/ThreadPool.cs	28 May 2004 22:17:41 -0000	1.7
--- runtime/System/Threading/ThreadPool.cs	1 Jun 2004 17:51:34 -0000
***************
*** 42,47 ****
--- 42,48 ----
  	// Internal state.
  	private static int usedWorkerThreads;
  	private static int usedCompletionThreads;
+ 	private static int queuedCompletionItems;
  	private static WorkItem workItems, lastWorkItem;
  	private static WorkItem completionItems, lastCompletionItem;
  	private static Thread[] workerThreads;
***************
*** 350,366 ****
  							}
  						}
  						while (item == null);
  					}
  					
  					try
  					{
- 						Interlocked.Increment(ref usedCompletionThreads);
  						item.Execute();
  					}
  					finally
  					{
  						item = null;
! 						Interlocked.Decrement(ref usedCompletionThreads);
  					}
  				}
  			}
--- 351,369 ----
  							}
  						}
  						while (item == null);
+ 						usedCompletionThreads++;
+ 						queuedCompletionItems--;
  					}
  					
  					try
  					{
  						item.Execute();
  					}
  					finally
  					{
  						item = null;
! 						lock(completionWait)
! 							usedCompletionThreads--;
  					}
  				}
  			}
***************
*** 440,446 ****
  						completionItems = item;
  					}
  					lastCompletionItem = item;
! 	
  					// We don't have threads, so execute the items now.
  					WorkItem next = CompletionItemToDispatch();
  					while(next != null)
--- 443,449 ----
  						completionItems = item;
  					}
  					lastCompletionItem = item;
! 
  					// We don't have threads, so execute the items now.
  					WorkItem next = CompletionItemToDispatch();
  					while(next != null)
***************
*** 462,477 ****
  							completionItems = item;
  						}
  						lastCompletionItem = item;
  
! 						// Determine if we need to spawn a new completion thread.
! 						if(completionItems != null &&
! 							numCompletionThreads < MaxCompletionThreads)
! 						{
! 							if(completionThreads == null)
! 							{
  								completionThreads =
  									new Thread [MaxCompletionThreads];
! 							}
  							Thread thread =
  								new Thread(new ThreadStart(Complete));
  						#if !ECMA_COMPAT
--- 465,491 ----
  							completionItems = item;
  						}
  						lastCompletionItem = item;
+ 						queuedCompletionItems++;
  
! 						if( completionThreads == null )
  								completionThreads =
  									new Thread [MaxCompletionThreads];
! 
! 						//
! 						// We need to make sure that there are enough threads to
! 						// handle the entire queue.
! 						//
! 						// There is a small possibility here that there is a thread
! 						// about to end that could take this work unit, but we have no
! 						// way of knowing that.
! 						//
! 						int needThreads = usedCompletionThreads + queuedCompletionItems;
! 
! 						// Determine if we need to spawn a new completion thread.
! 						if( needThreads > numCompletionThreads )
! 						{
! 							if( needThreads > MaxCompletionThreads )
! 								throw new SystemException("Number of completion threads required exceeds maximum");
  							Thread thread =
  								new Thread(new ThreadStart(Complete));
  						#if !ECMA_COMPAT
***************
*** 481,487 ****
  							thread.IsBackground = true;
  							thread.Start();
  						}
! 						Monitor.Pulse(completionWait);
  					}
  				}
  			}
--- 495,505 ----
  							thread.IsBackground = true;
  							thread.Start();
  						}
! 						else
! 						{
! 							// Signal one of our waiting threads
! 							Monitor.Pulse(completionWait);
! 						}
  					}
  				}
  			}
#### End of Patch data ####
