[LoongArch64] Part-5:add loongarch support in some files for LoongArch64. (#21769)
[mono-project.git] / mcs / class / System.Runtime.Remoting / System.Runtime.Remoting.Channels / RemotingThreadPool.cs
blob123cbaf860e90197147ce944e1943ccc059bf010
1 //
2 // System.Runtime.Remoting.Channels.RemotingThreadPool.cs
3 //
4 // Author: Lluis Sanchez Gual (lluis@ximian.com)
5 //
6 // 2005 (C) Copyright, Novell, Inc.
7 //
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System;
31 using System.Collections;
32 using System.Threading;
34 namespace System.Runtime.Remoting.Channels
36 internal class RemotingThreadPool
38 const int ThreadLimit = 1000;
39 const int ThreadWaitTime = 20000; //ms
40 const int PoolGrowDelay = 500; // ms
41 const int MinThreads = 3;
43 int freeThreads;
44 int poolUsers;
45 Queue workItems = new Queue ();
46 AutoResetEvent threadDone = new AutoResetEvent (false);
47 ArrayList runningThreads = new ArrayList ();
49 bool stopped = false;
51 static object globalLock = new object ();
52 static RemotingThreadPool sharedPool;
54 public static RemotingThreadPool GetSharedPool ()
56 lock (globalLock) {
57 if (sharedPool == null)
58 sharedPool = new RemotingThreadPool ();
59 sharedPool.poolUsers++;
61 return sharedPool;
64 public void Free ()
66 lock (globalLock) {
67 if (--poolUsers > 0)
68 return;
70 lock (workItems) {
71 stopped = true;
72 threadDone.Set ();
73 workItems.Clear ();
74 foreach (Thread t in runningThreads)
75 t.Abort ();
76 runningThreads.Clear ();
78 if (this == sharedPool)
79 sharedPool = null;
83 public bool RunThread (ThreadStart threadStart)
85 lock (workItems) {
86 if (stopped)
87 throw new RemotingException ("Server channel stopped.");
89 if (freeThreads > 0) {
90 freeThreads--;
91 workItems.Enqueue (threadStart);
92 Monitor.Pulse (workItems);
93 return true;
94 } else if (runningThreads.Count < MinThreads) {
95 workItems.Enqueue (threadStart);
96 StartPoolThread ();
97 return true;
101 // Try again some ms later, and if there are still no free threads,
102 // then create a new one
104 threadDone.WaitOne (PoolGrowDelay, false);
106 lock (workItems) {
107 if (stopped)
108 throw new RemotingException ("Server channel stopped.");
110 if (freeThreads > 0) {
111 freeThreads--;
112 workItems.Enqueue (threadStart);
113 Monitor.Pulse (workItems);
114 } else {
115 if (runningThreads.Count >= ThreadLimit)
116 return false;
117 workItems.Enqueue (threadStart);
118 StartPoolThread ();
121 return true;
124 void StartPoolThread ()
126 Thread thread = new Thread (new ThreadStart (PoolThread));
127 runningThreads.Add (thread);
128 thread.IsBackground = true;
129 thread.Start ();
132 void PoolThread ()
134 while (true) {
135 ThreadStart work = null;
136 do {
137 lock (workItems) {
138 if (workItems.Count > 0)
139 work = (ThreadStart) workItems.Dequeue ();
140 else {
141 freeThreads ++;
142 threadDone.Set ();
143 if (!Monitor.Wait (workItems, ThreadWaitTime)) {
144 // Maybe it timed out when the work was being queued.
145 if (workItems.Count > 0) {
146 work = (ThreadStart) workItems.Dequeue ();
147 } else {
148 freeThreads --;
149 if (freeThreads == 0) threadDone.Reset ();
150 runningThreads.Remove (Thread.CurrentThread);
151 return;
156 } while (work == null);
157 try {
158 work ();
160 catch (Exception ex)
162 #if DEBUG
163 Console.WriteLine("The exception was caught during RemotingThreadPool.PoolThread - work: {0}, {1}", ex.GetType(), ex.Message);
164 #endif