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