using System; using System.Collections.Generic; using ST = System.Threading; namespace SharpCifs.Util.Sharpen { class ThreadPoolExecutor { ThreadFactory _tf; int _corePoolSize; int _maxPoolSize; List _pool = new List (); int _runningThreads; int _freeThreads; bool _shutdown; Queue _pendingTasks = new Queue (); public ThreadPoolExecutor (int corePoolSize, ThreadFactory factory) { this._corePoolSize = corePoolSize; _maxPoolSize = corePoolSize; _tf = factory; } public void SetMaximumPoolSize (int size) { _maxPoolSize = size; } public bool IsShutdown () { return _shutdown; } public virtual bool IsTerminated () { lock (_pendingTasks) { return _shutdown && _pendingTasks.Count == 0; } } public virtual bool IsTerminating () { lock (_pendingTasks) { return _shutdown && !IsTerminated (); } } public int GetCorePoolSize () { return _corePoolSize; } public void PrestartAllCoreThreads () { lock (_pendingTasks) { while (_runningThreads < _corePoolSize) StartPoolThread (); } } public void SetThreadFactory (ThreadFactory f) { _tf = f; } public void Execute (IRunnable r) { InternalExecute (r, true); } internal void InternalExecute (IRunnable r, bool checkShutdown) { lock (_pendingTasks) { if (_shutdown && checkShutdown) throw new InvalidOperationException (); if (_runningThreads < _corePoolSize) { StartPoolThread (); } else if (_freeThreads > 0) { _freeThreads--; } else if (_runningThreads < _maxPoolSize) { StartPoolThread (); } _pendingTasks.Enqueue (r); ST.Monitor.PulseAll (_pendingTasks); } } void StartPoolThread () { _runningThreads++; _pool.Add (_tf.NewThread (new RunnableAction (RunPoolThread))); } public void RunPoolThread () { while (!IsTerminated ()) { try { IRunnable r = null; lock (_pendingTasks) { _freeThreads++; while (!IsTerminated () && _pendingTasks.Count == 0) ST.Monitor.Wait (_pendingTasks); if (IsTerminated ()) break; r = _pendingTasks.Dequeue (); } if (r != null) r.Run (); } //supress all errors, anyway //catch (ST.ThreadAbortException) { // // Do not catch a thread abort. If we've been aborted just let the thread die. // // Currently reseting an abort which was issued because the appdomain is being // // torn down results in the process living forever and consuming 100% cpu time. // return; //} catch { } } } public virtual void Shutdown () { lock (_pendingTasks) { _shutdown = true; ST.Monitor.PulseAll (_pendingTasks); } } public virtual List ShutdownNow () { lock (_pendingTasks) { _shutdown = true; foreach (var t in _pool) { try { t.Abort (); } catch {} } _pool.Clear (); _freeThreads = 0; _runningThreads = 0; var res = new List (_pendingTasks); _pendingTasks.Clear (); return res; } } } class RunnableAction: IRunnable { Action _action; public RunnableAction (Action a) { _action = a; } public void Run () { _action (); } } }