aboutsummaryrefslogtreecommitdiff
path: root/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ThreadPoolExecutor.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ThreadPoolExecutor.cs')
-rw-r--r--Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ThreadPoolExecutor.cs166
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 ();
+ }
+ }
+}