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