1 | // |
2 | // ThreadPool.h |
3 | // |
4 | // Library: Foundation |
5 | // Package: Threading |
6 | // Module: ThreadPool |
7 | // |
8 | // Definition of the ThreadPool class. |
9 | // |
10 | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
11 | // and Contributors. |
12 | // |
13 | // SPDX-License-Identifier: BSL-1.0 |
14 | // |
15 | |
16 | |
17 | #ifndef Foundation_ThreadPool_INCLUDED |
18 | #define Foundation_ThreadPool_INCLUDED |
19 | |
20 | |
21 | #include "Poco/Foundation.h" |
22 | #include "Poco/Thread.h" |
23 | #include "Poco/Mutex.h" |
24 | #include <vector> |
25 | |
26 | |
27 | namespace Poco { |
28 | |
29 | |
30 | class Runnable; |
31 | class PooledThread; |
32 | |
33 | class Foundation_API ThreadPool |
34 | /// A thread pool always keeps a number of threads running, ready |
35 | /// to accept work. |
36 | /// Creating and starting a threads can impose a significant runtime |
37 | /// overhead to an application. A thread pool helps to improve |
38 | /// the performance of an application by reducing the number |
39 | /// of threads that have to be created (and destroyed again). |
40 | /// Threads in a thread pool are re-used once they become |
41 | /// available again. |
42 | /// The thread pool always keeps a minimum number of threads |
43 | /// running. If the demand for threads increases, additional |
44 | /// threads are created. Once the demand for threads sinks |
45 | /// again, no-longer used threads are stopped and removed |
46 | /// from the pool. |
47 | { |
48 | public: |
49 | enum ThreadAffinityPolicy |
50 | { |
51 | TAP_DEFAULT = 0, |
52 | TAP_UNIFORM_DISTRIBUTION, |
53 | TAP_CUSTOM |
54 | }; |
55 | |
56 | ThreadPool(int minCapacity = 2, |
57 | int maxCapacity = 16, |
58 | int idleTime = 60, |
59 | int stackSize = POCO_THREAD_STACK_SIZE, |
60 | ThreadAffinityPolicy affinityPolicy = TAP_DEFAULT); |
61 | /// Creates a thread pool with minCapacity threads. |
62 | /// If required, up to maxCapacity threads are created |
63 | /// a NoThreadAvailableException exception is thrown. |
64 | /// If a thread is running idle for more than idleTime seconds, |
65 | /// and more than minCapacity threads are running, the thread |
66 | /// is killed. Threads are created with given stack size. |
67 | /// Threads are created with given affinity policy. |
68 | |
69 | ThreadPool(const std::string& name, |
70 | int minCapacity = 2, |
71 | int maxCapacity = 16, |
72 | int idleTime = 60, |
73 | int stackSize = POCO_THREAD_STACK_SIZE, |
74 | ThreadAffinityPolicy affinityPolicy = TAP_DEFAULT); |
75 | /// Creates a thread pool with the given name and minCapacity threads. |
76 | /// If required, up to maxCapacity threads are created |
77 | /// a NoThreadAvailableException exception is thrown. |
78 | /// If a thread is running idle for more than idleTime seconds, |
79 | /// and more than minCapacity threads are running, the thread |
80 | /// is killed. Threads are created with given stack size. |
81 | /// Threads are created with given affinity policy. |
82 | |
83 | ~ThreadPool(); |
84 | /// Currently running threads will remain active |
85 | /// until they complete. |
86 | |
87 | void addCapacity(int n); |
88 | /// Increases (or decreases, if n is negative) |
89 | /// the maximum number of threads. |
90 | |
91 | int capacity() const; |
92 | /// Returns the maximum capacity of threads. |
93 | |
94 | void setStackSize(int stackSize); |
95 | /// Sets the stack size for threads. |
96 | /// New stack size applies only for newly created threads. |
97 | |
98 | int getStackSize() const; |
99 | /// Returns the stack size used to create new threads. |
100 | |
101 | void setAffinityPolicy(ThreadAffinityPolicy affinityPolicy); |
102 | /// Sets the thread affinity policy for newly created threads. |
103 | |
104 | ThreadAffinityPolicy getAffinityPolicy(); |
105 | /// Returns the thread affinity policy used to create new threads. |
106 | |
107 | int used() const; |
108 | /// Returns the number of currently used threads. |
109 | |
110 | int allocated() const; |
111 | /// Returns the number of currently allocated threads. |
112 | |
113 | int available() const; |
114 | /// Returns the number available threads. |
115 | |
116 | void start(Runnable& target, int cpu = -1); |
117 | /// Obtains a thread and starts the target on specified cpu. |
118 | /// Throws a NoThreadAvailableException if no more |
119 | /// threads are available. |
120 | |
121 | void start(Runnable& target, const std::string& name, int cpu = -1); |
122 | /// Obtains a thread and starts the target on specified cpu. |
123 | /// Assigns the given name to the thread. |
124 | /// Throws a NoThreadAvailableException if no more |
125 | /// threads are available. |
126 | |
127 | void startWithPriority(Thread::Priority priority, Runnable& target, int cpu = -1); |
128 | /// Obtains a thread, adjusts the thread's priority, and starts the target on specified cpu. |
129 | /// Throws a NoThreadAvailableException if no more |
130 | /// threads are available. |
131 | |
132 | void startWithPriority(Thread::Priority priority, Runnable& target, const std::string& name, int cpu = -1); |
133 | /// Obtains a thread, adjusts the thread's priority, and starts the target on specified cpu. |
134 | /// Assigns the given name to the thread. |
135 | /// Throws a NoThreadAvailableException if no more |
136 | /// threads are available. |
137 | |
138 | void stopAll(); |
139 | /// Stops all running threads and waits for their completion. |
140 | /// |
141 | /// Will also delete all thread objects. |
142 | /// If used, this method should be the last action before |
143 | /// the thread pool is deleted. |
144 | /// |
145 | /// Note: If a thread fails to stop within 10 seconds |
146 | /// (due to a programming error, for example), the |
147 | /// underlying thread object will not be deleted and |
148 | /// this method will return anyway. This allows for a |
149 | /// more or less graceful shutdown in case of a misbehaving |
150 | /// thread. |
151 | |
152 | void joinAll(); |
153 | /// Waits for all threads to complete. |
154 | /// |
155 | /// Note that this will not actually join() the underlying |
156 | /// thread, but rather wait for the thread's runnables |
157 | /// to finish. |
158 | |
159 | void collect(); |
160 | /// Stops and removes no longer used threads from the |
161 | /// thread pool. Can be called at various times in an |
162 | /// application's life time to help the thread pool |
163 | /// manage its threads. Calling this method is optional, |
164 | /// as the thread pool is also implicitly managed in |
165 | /// calls to start(), addCapacity() and joinAll(). |
166 | |
167 | const std::string& name() const; |
168 | /// Returns the name of the thread pool, |
169 | /// or an empty string if no name has been |
170 | /// specified in the constructor. |
171 | |
172 | static ThreadPool& defaultPool(ThreadAffinityPolicy affinityPolicy = TAP_DEFAULT); |
173 | /// Returns a reference to the default |
174 | /// thread pool. |
175 | |
176 | protected: |
177 | PooledThread* getThread(); |
178 | PooledThread* createThread(); |
179 | |
180 | void housekeep(); |
181 | int affinity(int cpu); |
182 | |
183 | private: |
184 | ThreadPool(const ThreadPool& pool); |
185 | ThreadPool& operator = (const ThreadPool& pool); |
186 | |
187 | typedef std::vector<PooledThread*> ThreadVec; |
188 | |
189 | std::string _name; |
190 | int _minCapacity; |
191 | int _maxCapacity; |
192 | int _idleTime; |
193 | int _serial; |
194 | int _age; |
195 | int _stackSize; |
196 | ThreadVec _threads; |
197 | mutable FastMutex _mutex; |
198 | ThreadAffinityPolicy _affinityPolicy; |
199 | AtomicCounter _lastCpu; |
200 | }; |
201 | |
202 | |
203 | // |
204 | // inlines |
205 | // |
206 | inline void ThreadPool::setStackSize(int stackSize) |
207 | { |
208 | _stackSize = stackSize; |
209 | } |
210 | |
211 | |
212 | inline int ThreadPool::getStackSize() const |
213 | { |
214 | return _stackSize; |
215 | } |
216 | |
217 | |
218 | inline void ThreadPool::setAffinityPolicy(ThreadPool::ThreadAffinityPolicy affinityPolicy) |
219 | { |
220 | _affinityPolicy = affinityPolicy; |
221 | } |
222 | |
223 | |
224 | inline ThreadPool::ThreadAffinityPolicy ThreadPool::getAffinityPolicy() |
225 | { |
226 | return _affinityPolicy; |
227 | } |
228 | |
229 | |
230 | inline const std::string& ThreadPool::name() const |
231 | { |
232 | return _name; |
233 | } |
234 | |
235 | |
236 | } // namespace Poco |
237 | |
238 | |
239 | #endif // Foundation_ThreadPool_INCLUDED |
240 | |