]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | // |
2 | // thread_pool.hpp | |
3 | // ~~~~~~~~~~~~~~~ | |
4 | // | |
11fdf7f2 | 5 | // Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
b32b8144 FG |
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 io_context, 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 | // The underlying scheduler. | |
105 | detail::scheduler& scheduler_; | |
106 | ||
107 | // The threads in the pool. | |
108 | detail::thread_group threads_; | |
109 | }; | |
110 | ||
111 | /// Executor used to submit functions to a thread pool. | |
112 | class thread_pool::executor_type | |
113 | { | |
114 | public: | |
115 | /// Obtain the underlying execution context. | |
116 | thread_pool& context() const BOOST_ASIO_NOEXCEPT; | |
117 | ||
118 | /// Inform the thread pool that it has some outstanding work to do. | |
119 | /** | |
120 | * This function is used to inform the thread pool that some work has begun. | |
121 | * This ensures that the thread pool's join() function will not return while | |
122 | * the work is underway. | |
123 | */ | |
124 | void on_work_started() const BOOST_ASIO_NOEXCEPT; | |
125 | ||
126 | /// Inform the thread pool that some work is no longer outstanding. | |
127 | /** | |
128 | * This function is used to inform the thread pool that some work has | |
129 | * finished. Once the count of unfinished work reaches zero, the thread | |
130 | * pool's join() function is permitted to exit. | |
131 | */ | |
132 | void on_work_finished() const BOOST_ASIO_NOEXCEPT; | |
133 | ||
134 | /// Request the thread pool to invoke the given function object. | |
135 | /** | |
136 | * This function is used to ask the thread pool to execute the given function | |
137 | * object. If the current thread belongs to the pool, @c dispatch() executes | |
138 | * the function before returning. Otherwise, the function will be scheduled | |
139 | * to run on the thread pool. | |
140 | * | |
141 | * @param f The function object to be called. The executor will make | |
142 | * a copy of the handler object as required. The function signature of the | |
143 | * function object must be: @code void function(); @endcode | |
144 | * | |
145 | * @param a An allocator that may be used by the executor to allocate the | |
146 | * internal storage needed for function invocation. | |
147 | */ | |
148 | template <typename Function, typename Allocator> | |
149 | void dispatch(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const; | |
150 | ||
151 | /// Request the thread pool to invoke the given function object. | |
152 | /** | |
153 | * This function is used to ask the thread pool to execute the given function | |
154 | * object. The function object will never be executed inside @c post(). | |
155 | * Instead, it will be scheduled to run on the thread pool. | |
156 | * | |
157 | * @param f The function object to be called. The executor will make | |
158 | * a copy of the handler object as required. The function signature of the | |
159 | * function object must be: @code void function(); @endcode | |
160 | * | |
161 | * @param a An allocator that may be used by the executor to allocate the | |
162 | * internal storage needed for function invocation. | |
163 | */ | |
164 | template <typename Function, typename Allocator> | |
165 | void post(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const; | |
166 | ||
167 | /// Request the thread pool to invoke the given function object. | |
168 | /** | |
169 | * This function is used to ask the thread pool to execute the given function | |
170 | * object. The function object will never be executed inside @c defer(). | |
171 | * Instead, it will be scheduled to run on the thread pool. | |
172 | * | |
173 | * If the current thread belongs to the thread pool, @c defer() will delay | |
174 | * scheduling the function object until the current thread returns control to | |
175 | * the pool. | |
176 | * | |
177 | * @param f The function object to be called. The executor will make | |
178 | * a copy of the handler object as required. The function signature of the | |
179 | * function object must be: @code void function(); @endcode | |
180 | * | |
181 | * @param a An allocator that may be used by the executor to allocate the | |
182 | * internal storage needed for function invocation. | |
183 | */ | |
184 | template <typename Function, typename Allocator> | |
185 | void defer(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const; | |
186 | ||
187 | /// Determine whether the thread pool is running in the current thread. | |
188 | /** | |
189 | * @return @c true if the current thread belongs to the pool. Otherwise | |
190 | * returns @c false. | |
191 | */ | |
192 | bool running_in_this_thread() const BOOST_ASIO_NOEXCEPT; | |
193 | ||
194 | /// Compare two executors for equality. | |
195 | /** | |
196 | * Two executors are equal if they refer to the same underlying thread pool. | |
197 | */ | |
198 | friend bool operator==(const executor_type& a, | |
199 | const executor_type& b) BOOST_ASIO_NOEXCEPT | |
200 | { | |
201 | return &a.pool_ == &b.pool_; | |
202 | } | |
203 | ||
204 | /// Compare two executors for inequality. | |
205 | /** | |
206 | * Two executors are equal if they refer to the same underlying thread pool. | |
207 | */ | |
208 | friend bool operator!=(const executor_type& a, | |
209 | const executor_type& b) BOOST_ASIO_NOEXCEPT | |
210 | { | |
211 | return &a.pool_ != &b.pool_; | |
212 | } | |
213 | ||
214 | private: | |
215 | friend class thread_pool; | |
216 | ||
217 | // Constructor. | |
218 | explicit executor_type(thread_pool& p) : pool_(p) {} | |
219 | ||
220 | // The underlying thread pool. | |
221 | thread_pool& pool_; | |
222 | }; | |
223 | ||
224 | } // namespace asio | |
225 | } // namespace boost | |
226 | ||
227 | #include <boost/asio/detail/pop_options.hpp> | |
228 | ||
229 | #include <boost/asio/impl/thread_pool.hpp> | |
230 | #if defined(BOOST_ASIO_HEADER_ONLY) | |
231 | # include <boost/asio/impl/thread_pool.ipp> | |
232 | #endif // defined(BOOST_ASIO_HEADER_ONLY) | |
233 | ||
234 | #endif // BOOST_ASIO_THREAD_POOL_HPP |