]>
Commit | Line | Data |
---|---|---|
1 | // | |
2 | // thread_pool.hpp | |
3 | // ~~~~~~~~~~~~~~~ | |
4 | // | |
5 | // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) | |
6 | // | |
7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 | // | |
10 | ||
11 | #ifndef BOOST_ASIO_THREAD_POOL_HPP | |
12 | #define BOOST_ASIO_THREAD_POOL_HPP | |
13 | ||
14 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) | |
15 | # pragma once | |
16 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) | |
17 | ||
18 | #include <boost/asio/detail/config.hpp> | |
19 | #include <boost/asio/detail/noncopyable.hpp> | |
20 | #include <boost/asio/detail/scheduler.hpp> | |
21 | #include <boost/asio/detail/thread_group.hpp> | |
22 | #include <boost/asio/execution_context.hpp> | |
23 | ||
24 | #include <boost/asio/detail/push_options.hpp> | |
25 | ||
26 | namespace boost { | |
27 | namespace asio { | |
28 | ||
29 | /// A simple fixed-size thread pool. | |
30 | /** | |
31 | * The thread pool class is an execution context where functions are permitted | |
32 | * to run on one of a fixed number of threads. | |
33 | * | |
34 | * @par Submitting tasks to the pool | |
35 | * | |
36 | * To submit functions to the thread_pool, use the @ref boost::asio::dispatch, | |
37 | * @ref boost::asio::post or @ref boost::asio::defer free functions. | |
38 | * | |
39 | * For example: | |
40 | * | |
41 | * @code void my_task() | |
42 | * { | |
43 | * ... | |
44 | * } | |
45 | * | |
46 | * ... | |
47 | * | |
48 | * // Launch the pool with four threads. | |
49 | * boost::asio::thread_pool pool(4); | |
50 | * | |
51 | * // Submit a function to the pool. | |
52 | * boost::asio::post(pool, my_task); | |
53 | * | |
54 | * // Submit a lambda object to the pool. | |
55 | * boost::asio::post(pool, | |
56 | * []() | |
57 | * { | |
58 | * ... | |
59 | * }); | |
60 | * | |
61 | * // Wait for all tasks in the pool to complete. | |
62 | * pool.join(); @endcode | |
63 | */ | |
64 | class thread_pool | |
65 | : public execution_context | |
66 | { | |
67 | public: | |
68 | class executor_type; | |
69 | ||
70 | /// Constructs a pool with an automatically determined number of threads. | |
71 | BOOST_ASIO_DECL thread_pool(); | |
72 | ||
73 | /// Constructs a pool with a specified number of threads. | |
74 | BOOST_ASIO_DECL thread_pool(std::size_t num_threads); | |
75 | ||
76 | /// Destructor. | |
77 | /** | |
78 | * Automatically stops and joins the pool, if not explicitly done beforehand. | |
79 | */ | |
80 | BOOST_ASIO_DECL ~thread_pool(); | |
81 | ||
82 | /// Obtains the executor associated with the pool. | |
83 | executor_type get_executor() BOOST_ASIO_NOEXCEPT; | |
84 | ||
85 | /// Stops the threads. | |
86 | /** | |
87 | * This function stops the threads as soon as possible. As a result of calling | |
88 | * @c stop(), pending function objects may be never be invoked. | |
89 | */ | |
90 | BOOST_ASIO_DECL void stop(); | |
91 | ||
92 | /// Joins the threads. | |
93 | /** | |
94 | * This function blocks until the threads in the pool have completed. If @c | |
95 | * stop() is not called prior to @c join(), the @c join() call will wait | |
96 | * until the pool has no more outstanding work. | |
97 | */ | |
98 | BOOST_ASIO_DECL void join(); | |
99 | ||
100 | private: | |
101 | friend class executor_type; | |
102 | struct thread_function; | |
103 | ||
104 | // Helper function to create the underlying scheduler. | |
105 | BOOST_ASIO_DECL detail::scheduler& add_scheduler(detail::scheduler* s); | |
106 | ||
107 | // The underlying scheduler. | |
108 | detail::scheduler& scheduler_; | |
109 | ||
110 | // The threads in the pool. | |
111 | detail::thread_group threads_; | |
112 | }; | |
113 | ||
114 | /// Executor used to submit functions to a thread pool. | |
115 | class thread_pool::executor_type | |
116 | { | |
117 | public: | |
118 | /// Obtain the underlying execution context. | |
119 | thread_pool& context() const BOOST_ASIO_NOEXCEPT; | |
120 | ||
121 | /// Inform the thread pool that it has some outstanding work to do. | |
122 | /** | |
123 | * This function is used to inform the thread pool that some work has begun. | |
124 | * This ensures that the thread pool's join() function will not return while | |
125 | * the work is underway. | |
126 | */ | |
127 | void on_work_started() const BOOST_ASIO_NOEXCEPT; | |
128 | ||
129 | /// Inform the thread pool that some work is no longer outstanding. | |
130 | /** | |
131 | * This function is used to inform the thread pool that some work has | |
132 | * finished. Once the count of unfinished work reaches zero, the thread | |
133 | * pool's join() function is permitted to exit. | |
134 | */ | |
135 | void on_work_finished() const BOOST_ASIO_NOEXCEPT; | |
136 | ||
137 | /// Request the thread pool to invoke the given function object. | |
138 | /** | |
139 | * This function is used to ask the thread pool to execute the given function | |
140 | * object. If the current thread belongs to the pool, @c dispatch() executes | |
141 | * the function before returning. Otherwise, the function will be scheduled | |
142 | * to run on the thread pool. | |
143 | * | |
144 | * @param f The function object to be called. The executor will make | |
145 | * a copy of the handler object as required. The function signature of the | |
146 | * function object must be: @code void function(); @endcode | |
147 | * | |
148 | * @param a An allocator that may be used by the executor to allocate the | |
149 | * internal storage needed for function invocation. | |
150 | */ | |
151 | template <typename Function, typename Allocator> | |
152 | void dispatch(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const; | |
153 | ||
154 | /// Request the thread pool to invoke the given function object. | |
155 | /** | |
156 | * This function is used to ask the thread pool to execute the given function | |
157 | * object. The function object will never be executed inside @c post(). | |
158 | * Instead, it will be scheduled to run on the thread pool. | |
159 | * | |
160 | * @param f The function object to be called. The executor will make | |
161 | * a copy of the handler object as required. The function signature of the | |
162 | * function object must be: @code void function(); @endcode | |
163 | * | |
164 | * @param a An allocator that may be used by the executor to allocate the | |
165 | * internal storage needed for function invocation. | |
166 | */ | |
167 | template <typename Function, typename Allocator> | |
168 | void post(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const; | |
169 | ||
170 | /// Request the thread pool to invoke the given function object. | |
171 | /** | |
172 | * This function is used to ask the thread pool to execute the given function | |
173 | * object. The function object will never be executed inside @c defer(). | |
174 | * Instead, it will be scheduled to run on the thread pool. | |
175 | * | |
176 | * If the current thread belongs to the thread pool, @c defer() will delay | |
177 | * scheduling the function object until the current thread returns control to | |
178 | * the pool. | |
179 | * | |
180 | * @param f The function object to be called. The executor will make | |
181 | * a copy of the handler object as required. The function signature of the | |
182 | * function object must be: @code void function(); @endcode | |
183 | * | |
184 | * @param a An allocator that may be used by the executor to allocate the | |
185 | * internal storage needed for function invocation. | |
186 | */ | |
187 | template <typename Function, typename Allocator> | |
188 | void defer(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const; | |
189 | ||
190 | /// Determine whether the thread pool is running in the current thread. | |
191 | /** | |
192 | * @return @c true if the current thread belongs to the pool. Otherwise | |
193 | * returns @c false. | |
194 | */ | |
195 | bool running_in_this_thread() const BOOST_ASIO_NOEXCEPT; | |
196 | ||
197 | /// Compare two executors for equality. | |
198 | /** | |
199 | * Two executors are equal if they refer to the same underlying thread pool. | |
200 | */ | |
201 | friend bool operator==(const executor_type& a, | |
202 | const executor_type& b) BOOST_ASIO_NOEXCEPT | |
203 | { | |
204 | return &a.pool_ == &b.pool_; | |
205 | } | |
206 | ||
207 | /// Compare two executors for inequality. | |
208 | /** | |
209 | * Two executors are equal if they refer to the same underlying thread pool. | |
210 | */ | |
211 | friend bool operator!=(const executor_type& a, | |
212 | const executor_type& b) BOOST_ASIO_NOEXCEPT | |
213 | { | |
214 | return &a.pool_ != &b.pool_; | |
215 | } | |
216 | ||
217 | private: | |
218 | friend class thread_pool; | |
219 | ||
220 | // Constructor. | |
221 | explicit executor_type(thread_pool& p) : pool_(p) {} | |
222 | ||
223 | // The underlying thread pool. | |
224 | thread_pool& pool_; | |
225 | }; | |
226 | ||
227 | } // namespace asio | |
228 | } // namespace boost | |
229 | ||
230 | #include <boost/asio/detail/pop_options.hpp> | |
231 | ||
232 | #include <boost/asio/impl/thread_pool.hpp> | |
233 | #if defined(BOOST_ASIO_HEADER_ONLY) | |
234 | # include <boost/asio/impl/thread_pool.ipp> | |
235 | #endif // defined(BOOST_ASIO_HEADER_ONLY) | |
236 | ||
237 | #endif // BOOST_ASIO_THREAD_POOL_HPP |