diff options
Diffstat (limited to 'Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ThreadPoolExecutor.cs')
| -rw-r--r-- | Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ThreadPoolExecutor.cs | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ThreadPoolExecutor.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ThreadPoolExecutor.cs new file mode 100644 index 000000000..ef19b8bff --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ThreadPoolExecutor.cs @@ -0,0 +1,166 @@ +using System; +using System.Collections.Generic; +using ST = System.Threading; + +namespace SharpCifs.Util.Sharpen +{ + class ThreadPoolExecutor + { + ThreadFactory _tf; + int _corePoolSize; + int _maxPoolSize; + List<Thread> _pool = new List<Thread> (); + int _runningThreads; + int _freeThreads; + bool _shutdown; + Queue<IRunnable> _pendingTasks = new Queue<IRunnable> (); + + 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<IRunnable> ShutdownNow () + { + lock (_pendingTasks) { + _shutdown = true; + foreach (var t in _pool) { + try { + t.Abort (); + } catch {} + } + _pool.Clear (); + _freeThreads = 0; + _runningThreads = 0; + var res = new List<IRunnable> (_pendingTasks); + _pendingTasks.Clear (); + return res; + } + } + } + + class RunnableAction: IRunnable + { + Action _action; + + public RunnableAction (Action a) + { + _action = a; + } + + public void Run () + { + _action (); + } + } +} |
