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
27namespace Poco {
28
29
30class Runnable;
31class PooledThread;
32
33class 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{
48public:
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
176protected:
177 PooledThread* getThread();
178 PooledThread* createThread();
179
180 void housekeep();
181 int affinity(int cpu);
182
183private:
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//
206inline void ThreadPool::setStackSize(int stackSize)
207{
208 _stackSize = stackSize;
209}
210
211
212inline int ThreadPool::getStackSize() const
213{
214 return _stackSize;
215}
216
217
218inline void ThreadPool::setAffinityPolicy(ThreadPool::ThreadAffinityPolicy affinityPolicy)
219{
220 _affinityPolicy = affinityPolicy;
221}
222
223
224inline ThreadPool::ThreadAffinityPolicy ThreadPool::getAffinityPolicy()
225{
226 return _affinityPolicy;
227}
228
229
230inline const std::string& ThreadPool::name() const
231{
232 return _name;
233}
234
235
236} // namespace Poco
237
238
239#endif // Foundation_ThreadPool_INCLUDED
240