]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | // |
2 | // thread_pool.hpp | |
3 | // ~~~~~~~~~~~~~~~ | |
4 | // | |
1e59de90 | 5 | // Copyright (c) 2003-2022 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> | |
20effc67 | 19 | #include <boost/asio/detail/atomic_count.hpp> |
b32b8144 FG |
20 | #include <boost/asio/detail/scheduler.hpp> |
21 | #include <boost/asio/detail/thread_group.hpp> | |
20effc67 | 22 | #include <boost/asio/execution.hpp> |
b32b8144 FG |
23 | #include <boost/asio/execution_context.hpp> |
24 | ||
25 | #include <boost/asio/detail/push_options.hpp> | |
26 | ||
27 | namespace boost { | |
28 | namespace asio { | |
20effc67 TL |
29 | namespace detail { |
30 | struct thread_pool_bits | |
31 | { | |
32 | BOOST_ASIO_STATIC_CONSTEXPR(unsigned int, blocking_never = 1); | |
33 | BOOST_ASIO_STATIC_CONSTEXPR(unsigned int, blocking_always = 2); | |
34 | BOOST_ASIO_STATIC_CONSTEXPR(unsigned int, blocking_mask = 3); | |
35 | BOOST_ASIO_STATIC_CONSTEXPR(unsigned int, relationship_continuation = 4); | |
36 | BOOST_ASIO_STATIC_CONSTEXPR(unsigned int, outstanding_work_tracked = 8); | |
37 | }; | |
38 | } // namespace detail | |
b32b8144 FG |
39 | |
40 | /// A simple fixed-size thread pool. | |
41 | /** | |
42 | * The thread pool class is an execution context where functions are permitted | |
43 | * to run on one of a fixed number of threads. | |
44 | * | |
45 | * @par Submitting tasks to the pool | |
46 | * | |
20effc67 | 47 | * To submit functions to the thread pool, use the @ref boost::asio::dispatch, |
b32b8144 FG |
48 | * @ref boost::asio::post or @ref boost::asio::defer free functions. |
49 | * | |
50 | * For example: | |
51 | * | |
52 | * @code void my_task() | |
53 | * { | |
54 | * ... | |
55 | * } | |
56 | * | |
57 | * ... | |
58 | * | |
59 | * // Launch the pool with four threads. | |
60 | * boost::asio::thread_pool pool(4); | |
61 | * | |
62 | * // Submit a function to the pool. | |
63 | * boost::asio::post(pool, my_task); | |
64 | * | |
65 | * // Submit a lambda object to the pool. | |
66 | * boost::asio::post(pool, | |
67 | * []() | |
68 | * { | |
69 | * ... | |
70 | * }); | |
71 | * | |
72 | * // Wait for all tasks in the pool to complete. | |
73 | * pool.join(); @endcode | |
74 | */ | |
75 | class thread_pool | |
76 | : public execution_context | |
77 | { | |
78 | public: | |
20effc67 TL |
79 | template <typename Allocator, unsigned int Bits> |
80 | class basic_executor_type; | |
81 | ||
82 | template <typename Allocator, unsigned int Bits> | |
83 | friend class basic_executor_type; | |
84 | ||
85 | /// Executor used to submit functions to a thread pool. | |
86 | typedef basic_executor_type<std::allocator<void>, 0> executor_type; | |
b32b8144 | 87 | |
20effc67 TL |
88 | /// Scheduler used to schedule receivers on a thread pool. |
89 | typedef basic_executor_type<std::allocator<void>, 0> scheduler_type; | |
90 | ||
91 | #if !defined(BOOST_ASIO_NO_TS_EXECUTORS) | |
b32b8144 FG |
92 | /// Constructs a pool with an automatically determined number of threads. |
93 | BOOST_ASIO_DECL thread_pool(); | |
20effc67 | 94 | #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS) |
b32b8144 FG |
95 | |
96 | /// Constructs a pool with a specified number of threads. | |
97 | BOOST_ASIO_DECL thread_pool(std::size_t num_threads); | |
98 | ||
99 | /// Destructor. | |
100 | /** | |
101 | * Automatically stops and joins the pool, if not explicitly done beforehand. | |
102 | */ | |
103 | BOOST_ASIO_DECL ~thread_pool(); | |
104 | ||
105 | /// Obtains the executor associated with the pool. | |
106 | executor_type get_executor() BOOST_ASIO_NOEXCEPT; | |
107 | ||
20effc67 TL |
108 | /// Obtains the executor associated with the pool. |
109 | executor_type executor() BOOST_ASIO_NOEXCEPT; | |
110 | ||
111 | /// Obtains the scheduler associated with the pool. | |
112 | scheduler_type scheduler() BOOST_ASIO_NOEXCEPT; | |
113 | ||
b32b8144 FG |
114 | /// Stops the threads. |
115 | /** | |
116 | * This function stops the threads as soon as possible. As a result of calling | |
117 | * @c stop(), pending function objects may be never be invoked. | |
118 | */ | |
119 | BOOST_ASIO_DECL void stop(); | |
120 | ||
20effc67 TL |
121 | /// Attaches the current thread to the pool. |
122 | /** | |
123 | * This function attaches the current thread to the pool so that it may be | |
124 | * used for executing submitted function objects. Blocks the calling thread | |
125 | * until the pool is stopped or joined and has no outstanding work. | |
126 | */ | |
127 | BOOST_ASIO_DECL void attach(); | |
128 | ||
b32b8144 FG |
129 | /// Joins the threads. |
130 | /** | |
131 | * This function blocks until the threads in the pool have completed. If @c | |
132 | * stop() is not called prior to @c join(), the @c join() call will wait | |
133 | * until the pool has no more outstanding work. | |
134 | */ | |
135 | BOOST_ASIO_DECL void join(); | |
136 | ||
20effc67 TL |
137 | /// Waits for threads to complete. |
138 | /** | |
139 | * This function blocks until the threads in the pool have completed. If @c | |
140 | * stop() is not called prior to @c wait(), the @c wait() call will wait | |
141 | * until the pool has no more outstanding work. | |
142 | */ | |
143 | BOOST_ASIO_DECL void wait(); | |
144 | ||
b32b8144 | 145 | private: |
20effc67 TL |
146 | thread_pool(const thread_pool&) BOOST_ASIO_DELETED; |
147 | thread_pool& operator=(const thread_pool&) BOOST_ASIO_DELETED; | |
148 | ||
b32b8144 FG |
149 | struct thread_function; |
150 | ||
92f5a8d4 TL |
151 | // Helper function to create the underlying scheduler. |
152 | BOOST_ASIO_DECL detail::scheduler& add_scheduler(detail::scheduler* s); | |
153 | ||
b32b8144 FG |
154 | // The underlying scheduler. |
155 | detail::scheduler& scheduler_; | |
156 | ||
157 | // The threads in the pool. | |
158 | detail::thread_group threads_; | |
20effc67 TL |
159 | |
160 | // The current number of threads in the pool. | |
161 | detail::atomic_count num_threads_; | |
b32b8144 FG |
162 | }; |
163 | ||
20effc67 TL |
164 | /// Executor implementation type used to submit functions to a thread pool. |
165 | template <typename Allocator, unsigned int Bits> | |
166 | class thread_pool::basic_executor_type : detail::thread_pool_bits | |
b32b8144 FG |
167 | { |
168 | public: | |
20effc67 TL |
169 | /// The sender type, when this type is used as a scheduler. |
170 | typedef basic_executor_type sender_type; | |
171 | ||
172 | /// The bulk execution shape type. | |
173 | typedef std::size_t shape_type; | |
174 | ||
175 | /// The bulk execution index type. | |
176 | typedef std::size_t index_type; | |
177 | ||
178 | #if defined(BOOST_ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) \ | |
179 | && defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR) | |
180 | template < | |
181 | template <typename...> class Tuple, | |
182 | template <typename...> class Variant> | |
183 | using value_types = Variant<Tuple<>>; | |
184 | ||
185 | template <template <typename...> class Variant> | |
186 | using error_types = Variant<std::exception_ptr>; | |
187 | ||
188 | BOOST_ASIO_STATIC_CONSTEXPR(bool, sends_done = true); | |
189 | #endif // defined(BOOST_ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) | |
190 | // && defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR) | |
191 | ||
192 | /// Copy constructor. | |
193 | basic_executor_type( | |
194 | const basic_executor_type& other) BOOST_ASIO_NOEXCEPT | |
195 | : pool_(other.pool_), | |
196 | allocator_(other.allocator_), | |
197 | bits_(other.bits_) | |
198 | { | |
199 | if (Bits & outstanding_work_tracked) | |
200 | if (pool_) | |
201 | pool_->scheduler_.work_started(); | |
202 | } | |
203 | ||
204 | #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) | |
205 | /// Move constructor. | |
206 | basic_executor_type(basic_executor_type&& other) BOOST_ASIO_NOEXCEPT | |
207 | : pool_(other.pool_), | |
208 | allocator_(BOOST_ASIO_MOVE_CAST(Allocator)(other.allocator_)), | |
209 | bits_(other.bits_) | |
210 | { | |
211 | if (Bits & outstanding_work_tracked) | |
212 | other.pool_ = 0; | |
213 | } | |
214 | #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) | |
215 | ||
216 | /// Destructor. | |
217 | ~basic_executor_type() BOOST_ASIO_NOEXCEPT | |
218 | { | |
219 | if (Bits & outstanding_work_tracked) | |
220 | if (pool_) | |
221 | pool_->scheduler_.work_finished(); | |
222 | } | |
223 | ||
224 | /// Assignment operator. | |
225 | basic_executor_type& operator=( | |
226 | const basic_executor_type& other) BOOST_ASIO_NOEXCEPT; | |
227 | ||
228 | #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) | |
229 | /// Move assignment operator. | |
230 | basic_executor_type& operator=( | |
231 | basic_executor_type&& other) BOOST_ASIO_NOEXCEPT; | |
232 | #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) | |
233 | ||
1e59de90 TL |
234 | #if !defined(GENERATING_DOCUMENTATION) |
235 | private: | |
236 | friend struct boost_asio_require_fn::impl; | |
237 | friend struct boost_asio_prefer_fn::impl; | |
238 | #endif // !defined(GENERATING_DOCUMENTATION) | |
239 | ||
20effc67 TL |
240 | /// Obtain an executor with the @c blocking.possibly property. |
241 | /** | |
242 | * Do not call this function directly. It is intended for use with the | |
243 | * boost::asio::require customisation point. | |
244 | * | |
245 | * For example: | |
246 | * @code auto ex1 = my_thread_pool.executor(); | |
247 | * auto ex2 = boost::asio::require(ex1, | |
248 | * boost::asio::execution::blocking.possibly); @endcode | |
249 | */ | |
250 | BOOST_ASIO_CONSTEXPR basic_executor_type<Allocator, | |
251 | BOOST_ASIO_UNSPECIFIED(Bits & ~blocking_mask)> | |
252 | require(execution::blocking_t::possibly_t) const | |
253 | { | |
254 | return basic_executor_type<Allocator, Bits & ~blocking_mask>( | |
255 | pool_, allocator_, bits_ & ~blocking_mask); | |
256 | } | |
257 | ||
258 | /// Obtain an executor with the @c blocking.always property. | |
259 | /** | |
260 | * Do not call this function directly. It is intended for use with the | |
261 | * boost::asio::require customisation point. | |
262 | * | |
263 | * For example: | |
264 | * @code auto ex1 = my_thread_pool.executor(); | |
265 | * auto ex2 = boost::asio::require(ex1, | |
266 | * boost::asio::execution::blocking.always); @endcode | |
267 | */ | |
268 | BOOST_ASIO_CONSTEXPR basic_executor_type<Allocator, | |
269 | BOOST_ASIO_UNSPECIFIED((Bits & ~blocking_mask) | blocking_always)> | |
270 | require(execution::blocking_t::always_t) const | |
271 | { | |
272 | return basic_executor_type<Allocator, | |
273 | BOOST_ASIO_UNSPECIFIED((Bits & ~blocking_mask) | blocking_always)>( | |
274 | pool_, allocator_, bits_ & ~blocking_mask); | |
275 | } | |
276 | ||
277 | /// Obtain an executor with the @c blocking.never property. | |
278 | /** | |
279 | * Do not call this function directly. It is intended for use with the | |
280 | * boost::asio::require customisation point. | |
281 | * | |
282 | * For example: | |
283 | * @code auto ex1 = my_thread_pool.executor(); | |
284 | * auto ex2 = boost::asio::require(ex1, | |
285 | * boost::asio::execution::blocking.never); @endcode | |
286 | */ | |
287 | BOOST_ASIO_CONSTEXPR basic_executor_type<Allocator, | |
288 | BOOST_ASIO_UNSPECIFIED(Bits & ~blocking_mask)> | |
289 | require(execution::blocking_t::never_t) const | |
290 | { | |
291 | return basic_executor_type<Allocator, Bits & ~blocking_mask>( | |
292 | pool_, allocator_, (bits_ & ~blocking_mask) | blocking_never); | |
293 | } | |
294 | ||
295 | /// Obtain an executor with the @c relationship.fork property. | |
296 | /** | |
297 | * Do not call this function directly. It is intended for use with the | |
298 | * boost::asio::require customisation point. | |
299 | * | |
300 | * For example: | |
301 | * @code auto ex1 = my_thread_pool.executor(); | |
302 | * auto ex2 = boost::asio::require(ex1, | |
303 | * boost::asio::execution::relationship.fork); @endcode | |
304 | */ | |
305 | BOOST_ASIO_CONSTEXPR basic_executor_type require( | |
306 | execution::relationship_t::fork_t) const | |
307 | { | |
308 | return basic_executor_type(pool_, | |
309 | allocator_, bits_ & ~relationship_continuation); | |
310 | } | |
311 | ||
312 | /// Obtain an executor with the @c relationship.continuation property. | |
313 | /** | |
314 | * Do not call this function directly. It is intended for use with the | |
315 | * boost::asio::require customisation point. | |
316 | * | |
317 | * For example: | |
318 | * @code auto ex1 = my_thread_pool.executor(); | |
319 | * auto ex2 = boost::asio::require(ex1, | |
320 | * boost::asio::execution::relationship.continuation); @endcode | |
321 | */ | |
322 | BOOST_ASIO_CONSTEXPR basic_executor_type require( | |
323 | execution::relationship_t::continuation_t) const | |
324 | { | |
325 | return basic_executor_type(pool_, | |
326 | allocator_, bits_ | relationship_continuation); | |
327 | } | |
328 | ||
329 | /// Obtain an executor with the @c outstanding_work.tracked property. | |
330 | /** | |
331 | * Do not call this function directly. It is intended for use with the | |
332 | * boost::asio::require customisation point. | |
333 | * | |
334 | * For example: | |
335 | * @code auto ex1 = my_thread_pool.executor(); | |
336 | * auto ex2 = boost::asio::require(ex1, | |
337 | * boost::asio::execution::outstanding_work.tracked); @endcode | |
338 | */ | |
339 | BOOST_ASIO_CONSTEXPR basic_executor_type<Allocator, | |
340 | BOOST_ASIO_UNSPECIFIED(Bits | outstanding_work_tracked)> | |
341 | require(execution::outstanding_work_t::tracked_t) const | |
342 | { | |
343 | return basic_executor_type<Allocator, Bits | outstanding_work_tracked>( | |
344 | pool_, allocator_, bits_); | |
345 | } | |
346 | ||
347 | /// Obtain an executor with the @c outstanding_work.untracked property. | |
348 | /** | |
349 | * Do not call this function directly. It is intended for use with the | |
350 | * boost::asio::require customisation point. | |
351 | * | |
352 | * For example: | |
353 | * @code auto ex1 = my_thread_pool.executor(); | |
354 | * auto ex2 = boost::asio::require(ex1, | |
355 | * boost::asio::execution::outstanding_work.untracked); @endcode | |
356 | */ | |
357 | BOOST_ASIO_CONSTEXPR basic_executor_type<Allocator, | |
358 | BOOST_ASIO_UNSPECIFIED(Bits & ~outstanding_work_tracked)> | |
359 | require(execution::outstanding_work_t::untracked_t) const | |
360 | { | |
361 | return basic_executor_type<Allocator, Bits & ~outstanding_work_tracked>( | |
362 | pool_, allocator_, bits_); | |
363 | } | |
364 | ||
365 | /// Obtain an executor with the specified @c allocator property. | |
366 | /** | |
367 | * Do not call this function directly. It is intended for use with the | |
368 | * boost::asio::require customisation point. | |
369 | * | |
370 | * For example: | |
371 | * @code auto ex1 = my_thread_pool.executor(); | |
372 | * auto ex2 = boost::asio::require(ex1, | |
373 | * boost::asio::execution::allocator(my_allocator)); @endcode | |
374 | */ | |
375 | template <typename OtherAllocator> | |
376 | BOOST_ASIO_CONSTEXPR basic_executor_type<OtherAllocator, Bits> | |
377 | require(execution::allocator_t<OtherAllocator> a) const | |
378 | { | |
379 | return basic_executor_type<OtherAllocator, Bits>( | |
380 | pool_, a.value(), bits_); | |
381 | } | |
382 | ||
383 | /// Obtain an executor with the default @c allocator property. | |
384 | /** | |
385 | * Do not call this function directly. It is intended for use with the | |
386 | * boost::asio::require customisation point. | |
387 | * | |
388 | * For example: | |
389 | * @code auto ex1 = my_thread_pool.executor(); | |
390 | * auto ex2 = boost::asio::require(ex1, | |
391 | * boost::asio::execution::allocator); @endcode | |
392 | */ | |
393 | BOOST_ASIO_CONSTEXPR basic_executor_type<std::allocator<void>, Bits> | |
394 | require(execution::allocator_t<void>) const | |
395 | { | |
396 | return basic_executor_type<std::allocator<void>, Bits>( | |
397 | pool_, std::allocator<void>(), bits_); | |
398 | } | |
399 | ||
1e59de90 TL |
400 | #if !defined(GENERATING_DOCUMENTATION) |
401 | private: | |
402 | friend struct boost_asio_query_fn::impl; | |
403 | friend struct boost::asio::execution::detail::mapping_t<0>; | |
404 | friend struct boost::asio::execution::detail::outstanding_work_t<0>; | |
405 | #endif // !defined(GENERATING_DOCUMENTATION) | |
406 | ||
20effc67 TL |
407 | /// Query the current value of the @c bulk_guarantee property. |
408 | /** | |
409 | * Do not call this function directly. It is intended for use with the | |
410 | * boost::asio::query customisation point. | |
411 | * | |
412 | * For example: | |
413 | * @code auto ex = my_thread_pool.executor(); | |
414 | * if (boost::asio::query(ex, boost::asio::execution::bulk_guarantee) | |
415 | * == boost::asio::execution::bulk_guarantee.parallel) | |
416 | * ... @endcode | |
417 | */ | |
418 | static BOOST_ASIO_CONSTEXPR execution::bulk_guarantee_t query( | |
419 | execution::bulk_guarantee_t) BOOST_ASIO_NOEXCEPT | |
420 | { | |
421 | return execution::bulk_guarantee.parallel; | |
422 | } | |
423 | ||
424 | /// Query the current value of the @c mapping property. | |
425 | /** | |
426 | * Do not call this function directly. It is intended for use with the | |
427 | * boost::asio::query customisation point. | |
428 | * | |
429 | * For example: | |
430 | * @code auto ex = my_thread_pool.executor(); | |
431 | * if (boost::asio::query(ex, boost::asio::execution::mapping) | |
432 | * == boost::asio::execution::mapping.thread) | |
433 | * ... @endcode | |
434 | */ | |
435 | static BOOST_ASIO_CONSTEXPR execution::mapping_t query( | |
436 | execution::mapping_t) BOOST_ASIO_NOEXCEPT | |
437 | { | |
438 | return execution::mapping.thread; | |
439 | } | |
440 | ||
441 | /// Query the current value of the @c context property. | |
442 | /** | |
443 | * Do not call this function directly. It is intended for use with the | |
444 | * boost::asio::query customisation point. | |
445 | * | |
446 | * For example: | |
447 | * @code auto ex = my_thread_pool.executor(); | |
448 | * boost::asio::thread_pool& pool = boost::asio::query( | |
449 | * ex, boost::asio::execution::context); @endcode | |
450 | */ | |
451 | thread_pool& query(execution::context_t) const BOOST_ASIO_NOEXCEPT | |
452 | { | |
453 | return *pool_; | |
454 | } | |
455 | ||
456 | /// Query the current value of the @c blocking property. | |
457 | /** | |
458 | * Do not call this function directly. It is intended for use with the | |
459 | * boost::asio::query customisation point. | |
460 | * | |
461 | * For example: | |
462 | * @code auto ex = my_thread_pool.executor(); | |
463 | * if (boost::asio::query(ex, boost::asio::execution::blocking) | |
464 | * == boost::asio::execution::blocking.always) | |
465 | * ... @endcode | |
466 | */ | |
467 | BOOST_ASIO_CONSTEXPR execution::blocking_t query( | |
468 | execution::blocking_t) const BOOST_ASIO_NOEXCEPT | |
469 | { | |
470 | return (bits_ & blocking_never) | |
471 | ? execution::blocking_t(execution::blocking.never) | |
472 | : ((Bits & blocking_always) | |
473 | ? execution::blocking_t(execution::blocking.always) | |
474 | : execution::blocking_t(execution::blocking.possibly)); | |
475 | } | |
476 | ||
477 | /// Query the current value of the @c relationship property. | |
478 | /** | |
479 | * Do not call this function directly. It is intended for use with the | |
480 | * boost::asio::query customisation point. | |
481 | * | |
482 | * For example: | |
483 | * @code auto ex = my_thread_pool.executor(); | |
484 | * if (boost::asio::query(ex, boost::asio::execution::relationship) | |
485 | * == boost::asio::execution::relationship.continuation) | |
486 | * ... @endcode | |
487 | */ | |
488 | BOOST_ASIO_CONSTEXPR execution::relationship_t query( | |
489 | execution::relationship_t) const BOOST_ASIO_NOEXCEPT | |
490 | { | |
491 | return (bits_ & relationship_continuation) | |
492 | ? execution::relationship_t(execution::relationship.continuation) | |
493 | : execution::relationship_t(execution::relationship.fork); | |
494 | } | |
495 | ||
496 | /// Query the current value of the @c outstanding_work property. | |
497 | /** | |
498 | * Do not call this function directly. It is intended for use with the | |
499 | * boost::asio::query customisation point. | |
500 | * | |
501 | * For example: | |
502 | * @code auto ex = my_thread_pool.executor(); | |
503 | * if (boost::asio::query(ex, boost::asio::execution::outstanding_work) | |
504 | * == boost::asio::execution::outstanding_work.tracked) | |
505 | * ... @endcode | |
506 | */ | |
507 | static BOOST_ASIO_CONSTEXPR execution::outstanding_work_t query( | |
508 | execution::outstanding_work_t) BOOST_ASIO_NOEXCEPT | |
509 | { | |
510 | return (Bits & outstanding_work_tracked) | |
511 | ? execution::outstanding_work_t(execution::outstanding_work.tracked) | |
512 | : execution::outstanding_work_t(execution::outstanding_work.untracked); | |
513 | } | |
514 | ||
515 | /// Query the current value of the @c allocator property. | |
516 | /** | |
517 | * Do not call this function directly. It is intended for use with the | |
518 | * boost::asio::query customisation point. | |
519 | * | |
520 | * For example: | |
521 | * @code auto ex = my_thread_pool.executor(); | |
522 | * auto alloc = boost::asio::query(ex, | |
523 | * boost::asio::execution::allocator); @endcode | |
524 | */ | |
525 | template <typename OtherAllocator> | |
526 | BOOST_ASIO_CONSTEXPR Allocator query( | |
527 | execution::allocator_t<OtherAllocator>) const BOOST_ASIO_NOEXCEPT | |
528 | { | |
529 | return allocator_; | |
530 | } | |
531 | ||
532 | /// Query the current value of the @c allocator property. | |
533 | /** | |
534 | * Do not call this function directly. It is intended for use with the | |
535 | * boost::asio::query customisation point. | |
536 | * | |
537 | * For example: | |
538 | * @code auto ex = my_thread_pool.executor(); | |
539 | * auto alloc = boost::asio::query(ex, | |
540 | * boost::asio::execution::allocator); @endcode | |
541 | */ | |
542 | BOOST_ASIO_CONSTEXPR Allocator query( | |
543 | execution::allocator_t<void>) const BOOST_ASIO_NOEXCEPT | |
544 | { | |
545 | return allocator_; | |
546 | } | |
547 | ||
548 | /// Query the occupancy (recommended number of work items) for the pool. | |
549 | /** | |
550 | * Do not call this function directly. It is intended for use with the | |
551 | * boost::asio::query customisation point. | |
552 | * | |
553 | * For example: | |
554 | * @code auto ex = my_thread_pool.executor(); | |
555 | * std::size_t occupancy = boost::asio::query( | |
556 | * ex, boost::asio::execution::occupancy); @endcode | |
557 | */ | |
558 | std::size_t query(execution::occupancy_t) const BOOST_ASIO_NOEXCEPT | |
559 | { | |
560 | return static_cast<std::size_t>(pool_->num_threads_); | |
561 | } | |
562 | ||
1e59de90 | 563 | public: |
20effc67 TL |
564 | /// Determine whether the thread pool is running in the current thread. |
565 | /** | |
566 | * @return @c true if the current thread is running the thread pool. Otherwise | |
567 | * returns @c false. | |
568 | */ | |
569 | bool running_in_this_thread() const BOOST_ASIO_NOEXCEPT; | |
570 | ||
571 | /// Compare two executors for equality. | |
572 | /** | |
573 | * Two executors are equal if they refer to the same underlying thread pool. | |
574 | */ | |
575 | friend bool operator==(const basic_executor_type& a, | |
576 | const basic_executor_type& b) BOOST_ASIO_NOEXCEPT | |
577 | { | |
578 | return a.pool_ == b.pool_ | |
579 | && a.allocator_ == b.allocator_ | |
580 | && a.bits_ == b.bits_; | |
581 | } | |
582 | ||
583 | /// Compare two executors for inequality. | |
584 | /** | |
585 | * Two executors are equal if they refer to the same underlying thread pool. | |
586 | */ | |
587 | friend bool operator!=(const basic_executor_type& a, | |
588 | const basic_executor_type& b) BOOST_ASIO_NOEXCEPT | |
589 | { | |
590 | return a.pool_ != b.pool_ | |
591 | || a.allocator_ != b.allocator_ | |
592 | || a.bits_ != b.bits_; | |
593 | } | |
594 | ||
1e59de90 TL |
595 | #if !defined(GENERATING_DOCUMENTATION) |
596 | private: | |
597 | friend struct boost_asio_execution_execute_fn::impl; | |
598 | #endif // !defined(GENERATING_DOCUMENTATION) | |
599 | ||
20effc67 TL |
600 | /// Execution function. |
601 | /** | |
602 | * Do not call this function directly. It is intended for use with the | |
603 | * execution::execute customisation point. | |
604 | * | |
605 | * For example: | |
606 | * @code auto ex = my_thread_pool.executor(); | |
607 | * execution::execute(ex, my_function_object); @endcode | |
608 | */ | |
609 | template <typename Function> | |
610 | void execute(BOOST_ASIO_MOVE_ARG(Function) f) const | |
611 | { | |
612 | this->do_execute(BOOST_ASIO_MOVE_CAST(Function)(f), | |
613 | integral_constant<bool, (Bits & blocking_always) != 0>()); | |
614 | } | |
615 | ||
1e59de90 | 616 | public: |
20effc67 TL |
617 | /// Bulk execution function. |
618 | template <typename Function> | |
619 | void bulk_execute(BOOST_ASIO_MOVE_ARG(Function) f, std::size_t n) const | |
620 | { | |
621 | this->do_bulk_execute(BOOST_ASIO_MOVE_CAST(Function)(f), n, | |
622 | integral_constant<bool, (Bits & blocking_always) != 0>()); | |
623 | } | |
624 | ||
625 | /// Schedule function. | |
626 | /** | |
627 | * Do not call this function directly. It is intended for use with the | |
628 | * execution::schedule customisation point. | |
629 | * | |
630 | * @return An object that satisfies the sender concept. | |
631 | */ | |
632 | sender_type schedule() const BOOST_ASIO_NOEXCEPT | |
633 | { | |
634 | return *this; | |
635 | } | |
636 | ||
637 | /// Connect function. | |
638 | /** | |
639 | * Do not call this function directly. It is intended for use with the | |
640 | * execution::connect customisation point. | |
641 | * | |
642 | * @return An object of an unspecified type that satisfies the @c | |
643 | * operation_state concept. | |
644 | */ | |
645 | template <BOOST_ASIO_EXECUTION_RECEIVER_OF_0 Receiver> | |
646 | #if defined(GENERATING_DOCUMENTATION) | |
647 | unspecified | |
648 | #else // defined(GENERATING_DOCUMENTATION) | |
649 | execution::detail::as_operation<basic_executor_type, Receiver> | |
650 | #endif // defined(GENERATING_DOCUMENTATION) | |
651 | connect(BOOST_ASIO_MOVE_ARG(Receiver) r) const | |
652 | { | |
653 | return execution::detail::as_operation<basic_executor_type, Receiver>( | |
654 | *this, BOOST_ASIO_MOVE_CAST(Receiver)(r)); | |
655 | } | |
656 | ||
657 | #if !defined(BOOST_ASIO_NO_TS_EXECUTORS) | |
b32b8144 FG |
658 | /// Obtain the underlying execution context. |
659 | thread_pool& context() const BOOST_ASIO_NOEXCEPT; | |
660 | ||
661 | /// Inform the thread pool that it has some outstanding work to do. | |
662 | /** | |
663 | * This function is used to inform the thread pool that some work has begun. | |
664 | * This ensures that the thread pool's join() function will not return while | |
665 | * the work is underway. | |
666 | */ | |
667 | void on_work_started() const BOOST_ASIO_NOEXCEPT; | |
668 | ||
669 | /// Inform the thread pool that some work is no longer outstanding. | |
670 | /** | |
671 | * This function is used to inform the thread pool that some work has | |
672 | * finished. Once the count of unfinished work reaches zero, the thread | |
673 | * pool's join() function is permitted to exit. | |
674 | */ | |
675 | void on_work_finished() const BOOST_ASIO_NOEXCEPT; | |
676 | ||
677 | /// Request the thread pool to invoke the given function object. | |
678 | /** | |
679 | * This function is used to ask the thread pool to execute the given function | |
680 | * object. If the current thread belongs to the pool, @c dispatch() executes | |
681 | * the function before returning. Otherwise, the function will be scheduled | |
682 | * to run on the thread pool. | |
683 | * | |
684 | * @param f The function object to be called. The executor will make | |
685 | * a copy of the handler object as required. The function signature of the | |
686 | * function object must be: @code void function(); @endcode | |
687 | * | |
688 | * @param a An allocator that may be used by the executor to allocate the | |
689 | * internal storage needed for function invocation. | |
690 | */ | |
20effc67 TL |
691 | template <typename Function, typename OtherAllocator> |
692 | void dispatch(BOOST_ASIO_MOVE_ARG(Function) f, | |
693 | const OtherAllocator& a) const; | |
b32b8144 FG |
694 | |
695 | /// Request the thread pool to invoke the given function object. | |
696 | /** | |
697 | * This function is used to ask the thread pool to execute the given function | |
698 | * object. The function object will never be executed inside @c post(). | |
699 | * Instead, it will be scheduled to run on the thread pool. | |
700 | * | |
701 | * @param f The function object to be called. The executor will make | |
702 | * a copy of the handler object as required. The function signature of the | |
703 | * function object must be: @code void function(); @endcode | |
704 | * | |
705 | * @param a An allocator that may be used by the executor to allocate the | |
706 | * internal storage needed for function invocation. | |
707 | */ | |
20effc67 TL |
708 | template <typename Function, typename OtherAllocator> |
709 | void post(BOOST_ASIO_MOVE_ARG(Function) f, | |
710 | const OtherAllocator& a) const; | |
b32b8144 FG |
711 | |
712 | /// Request the thread pool to invoke the given function object. | |
713 | /** | |
714 | * This function is used to ask the thread pool to execute the given function | |
715 | * object. The function object will never be executed inside @c defer(). | |
716 | * Instead, it will be scheduled to run on the thread pool. | |
717 | * | |
718 | * If the current thread belongs to the thread pool, @c defer() will delay | |
719 | * scheduling the function object until the current thread returns control to | |
720 | * the pool. | |
721 | * | |
722 | * @param f The function object to be called. The executor will make | |
723 | * a copy of the handler object as required. The function signature of the | |
724 | * function object must be: @code void function(); @endcode | |
725 | * | |
726 | * @param a An allocator that may be used by the executor to allocate the | |
727 | * internal storage needed for function invocation. | |
728 | */ | |
20effc67 TL |
729 | template <typename Function, typename OtherAllocator> |
730 | void defer(BOOST_ASIO_MOVE_ARG(Function) f, | |
731 | const OtherAllocator& a) const; | |
732 | #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS) | |
b32b8144 | 733 | |
20effc67 TL |
734 | private: |
735 | friend class thread_pool; | |
736 | template <typename, unsigned int> friend class basic_executor_type; | |
b32b8144 | 737 | |
20effc67 TL |
738 | // Constructor used by thread_pool::get_executor(). |
739 | explicit basic_executor_type(thread_pool& p) BOOST_ASIO_NOEXCEPT | |
740 | : pool_(&p), | |
741 | allocator_(), | |
742 | bits_(0) | |
b32b8144 | 743 | { |
20effc67 TL |
744 | if (Bits & outstanding_work_tracked) |
745 | pool_->scheduler_.work_started(); | |
b32b8144 FG |
746 | } |
747 | ||
20effc67 TL |
748 | // Constructor used by require(). |
749 | basic_executor_type(thread_pool* p, | |
750 | const Allocator& a, unsigned int bits) BOOST_ASIO_NOEXCEPT | |
751 | : pool_(p), | |
752 | allocator_(a), | |
753 | bits_(bits) | |
b32b8144 | 754 | { |
20effc67 TL |
755 | if (Bits & outstanding_work_tracked) |
756 | if (pool_) | |
757 | pool_->scheduler_.work_started(); | |
b32b8144 FG |
758 | } |
759 | ||
20effc67 TL |
760 | /// Execution helper implementation for possibly and never blocking. |
761 | template <typename Function> | |
762 | void do_execute(BOOST_ASIO_MOVE_ARG(Function) f, false_type) const; | |
763 | ||
764 | /// Execution helper implementation for always blocking. | |
765 | template <typename Function> | |
766 | void do_execute(BOOST_ASIO_MOVE_ARG(Function) f, true_type) const; | |
b32b8144 | 767 | |
20effc67 TL |
768 | /// Bulk execution helper implementation for possibly and never blocking. |
769 | template <typename Function> | |
770 | void do_bulk_execute(BOOST_ASIO_MOVE_ARG(Function) f, | |
771 | std::size_t n, false_type) const; | |
772 | ||
773 | /// Bulk execution helper implementation for always blocking. | |
774 | template <typename Function> | |
775 | void do_bulk_execute(BOOST_ASIO_MOVE_ARG(Function) f, | |
776 | std::size_t n, true_type) const; | |
b32b8144 FG |
777 | |
778 | // The underlying thread pool. | |
20effc67 TL |
779 | thread_pool* pool_; |
780 | ||
781 | // The allocator used for execution functions. | |
782 | Allocator allocator_; | |
783 | ||
784 | // The runtime-switched properties of the thread pool executor. | |
785 | unsigned int bits_; | |
b32b8144 FG |
786 | }; |
787 | ||
20effc67 TL |
788 | #if !defined(GENERATING_DOCUMENTATION) |
789 | ||
790 | namespace traits { | |
791 | ||
792 | #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) | |
793 | ||
794 | template <typename Allocator, unsigned int Bits> | |
795 | struct equality_comparable< | |
796 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits> | |
797 | > | |
798 | { | |
799 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
800 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
801 | }; | |
802 | ||
803 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) | |
804 | ||
805 | #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) | |
806 | ||
807 | template <typename Allocator, unsigned int Bits, typename Function> | |
808 | struct execute_member< | |
809 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
810 | Function | |
811 | > | |
812 | { | |
813 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
814 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
815 | typedef void result_type; | |
816 | }; | |
817 | ||
818 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) | |
819 | ||
820 | #if !defined(BOOST_ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT) | |
821 | ||
822 | template <typename Allocator, unsigned int Bits> | |
823 | struct schedule_member< | |
824 | const boost::asio::thread_pool::basic_executor_type<Allocator, Bits> | |
825 | > | |
826 | { | |
827 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
828 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
829 | typedef boost::asio::thread_pool::basic_executor_type< | |
830 | Allocator, Bits> result_type; | |
831 | }; | |
832 | ||
833 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT) | |
834 | ||
835 | #if !defined(BOOST_ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT) | |
836 | ||
837 | template <typename Allocator, unsigned int Bits, typename Receiver> | |
838 | struct connect_member< | |
839 | const boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
840 | Receiver | |
841 | > | |
842 | { | |
843 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
844 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
845 | typedef boost::asio::execution::detail::as_operation< | |
846 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
847 | Receiver> result_type; | |
848 | }; | |
849 | ||
850 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT) | |
851 | ||
852 | #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) | |
853 | ||
854 | template <typename Allocator, unsigned int Bits> | |
855 | struct require_member< | |
856 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
857 | boost::asio::execution::blocking_t::possibly_t | |
858 | > : boost::asio::detail::thread_pool_bits | |
859 | { | |
860 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
861 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
862 | typedef boost::asio::thread_pool::basic_executor_type< | |
863 | Allocator, Bits & ~blocking_mask> result_type; | |
864 | }; | |
865 | ||
866 | template <typename Allocator, unsigned int Bits> | |
867 | struct require_member< | |
868 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
869 | boost::asio::execution::blocking_t::always_t | |
870 | > : boost::asio::detail::thread_pool_bits | |
871 | { | |
872 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
873 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
874 | typedef boost::asio::thread_pool::basic_executor_type<Allocator, | |
875 | (Bits & ~blocking_mask) | blocking_always> result_type; | |
876 | }; | |
877 | ||
878 | template <typename Allocator, unsigned int Bits> | |
879 | struct require_member< | |
880 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
881 | boost::asio::execution::blocking_t::never_t | |
882 | > : boost::asio::detail::thread_pool_bits | |
883 | { | |
884 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
885 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
886 | typedef boost::asio::thread_pool::basic_executor_type< | |
887 | Allocator, Bits & ~blocking_mask> result_type; | |
888 | }; | |
889 | ||
890 | template <typename Allocator, unsigned int Bits> | |
891 | struct require_member< | |
892 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
893 | boost::asio::execution::relationship_t::fork_t | |
894 | > | |
895 | { | |
896 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
897 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
898 | typedef boost::asio::thread_pool::basic_executor_type< | |
899 | Allocator, Bits> result_type; | |
900 | }; | |
901 | ||
902 | template <typename Allocator, unsigned int Bits> | |
903 | struct require_member< | |
904 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
905 | boost::asio::execution::relationship_t::continuation_t | |
906 | > | |
907 | { | |
908 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
909 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
910 | typedef boost::asio::thread_pool::basic_executor_type< | |
911 | Allocator, Bits> result_type; | |
912 | }; | |
913 | ||
914 | template <typename Allocator, unsigned int Bits> | |
915 | struct require_member< | |
916 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
917 | boost::asio::execution::outstanding_work_t::tracked_t | |
918 | > : boost::asio::detail::thread_pool_bits | |
919 | { | |
920 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
921 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
922 | typedef boost::asio::thread_pool::basic_executor_type< | |
923 | Allocator, Bits | outstanding_work_tracked> result_type; | |
924 | }; | |
925 | ||
926 | template <typename Allocator, unsigned int Bits> | |
927 | struct require_member< | |
928 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
929 | boost::asio::execution::outstanding_work_t::untracked_t | |
930 | > : boost::asio::detail::thread_pool_bits | |
931 | { | |
932 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
933 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
934 | typedef boost::asio::thread_pool::basic_executor_type< | |
935 | Allocator, Bits & ~outstanding_work_tracked> result_type; | |
936 | }; | |
937 | ||
938 | template <typename Allocator, unsigned int Bits> | |
939 | struct require_member< | |
940 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
941 | boost::asio::execution::allocator_t<void> | |
942 | > | |
943 | { | |
944 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
945 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
946 | typedef boost::asio::thread_pool::basic_executor_type< | |
947 | std::allocator<void>, Bits> result_type; | |
948 | }; | |
949 | ||
950 | template <unsigned int Bits, | |
951 | typename Allocator, typename OtherAllocator> | |
952 | struct require_member< | |
953 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
954 | boost::asio::execution::allocator_t<OtherAllocator> | |
955 | > | |
956 | { | |
957 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
958 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
959 | typedef boost::asio::thread_pool::basic_executor_type< | |
960 | OtherAllocator, Bits> result_type; | |
961 | }; | |
962 | ||
963 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) | |
964 | ||
965 | #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) | |
966 | ||
967 | template <typename Allocator, unsigned int Bits, typename Property> | |
968 | struct query_static_constexpr_member< | |
969 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
970 | Property, | |
971 | typename boost::asio::enable_if< | |
972 | boost::asio::is_convertible< | |
973 | Property, | |
974 | boost::asio::execution::bulk_guarantee_t | |
975 | >::value | |
976 | >::type | |
977 | > | |
978 | { | |
979 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
980 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
981 | typedef boost::asio::execution::bulk_guarantee_t::parallel_t result_type; | |
982 | ||
983 | static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT | |
984 | { | |
985 | return result_type(); | |
986 | } | |
987 | }; | |
988 | ||
989 | template <typename Allocator, unsigned int Bits, typename Property> | |
990 | struct query_static_constexpr_member< | |
991 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
992 | Property, | |
993 | typename boost::asio::enable_if< | |
994 | boost::asio::is_convertible< | |
995 | Property, | |
996 | boost::asio::execution::outstanding_work_t | |
997 | >::value | |
998 | >::type | |
999 | > : boost::asio::detail::thread_pool_bits | |
1000 | { | |
1001 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1002 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
1003 | typedef boost::asio::execution::outstanding_work_t result_type; | |
1004 | ||
1005 | static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT | |
1006 | { | |
1007 | return (Bits & outstanding_work_tracked) | |
1008 | ? execution::outstanding_work_t(execution::outstanding_work.tracked) | |
1009 | : execution::outstanding_work_t(execution::outstanding_work.untracked); | |
1010 | } | |
1011 | }; | |
1012 | ||
1013 | template <typename Allocator, unsigned int Bits, typename Property> | |
1014 | struct query_static_constexpr_member< | |
1015 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
1016 | Property, | |
1017 | typename boost::asio::enable_if< | |
1018 | boost::asio::is_convertible< | |
1019 | Property, | |
1020 | boost::asio::execution::mapping_t | |
1021 | >::value | |
1022 | >::type | |
1023 | > | |
1024 | { | |
1025 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1026 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
1027 | typedef boost::asio::execution::mapping_t::thread_t result_type; | |
1028 | ||
1029 | static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT | |
1030 | { | |
1031 | return result_type(); | |
1032 | } | |
1033 | }; | |
1034 | ||
1035 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) | |
1036 | ||
1037 | #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) | |
1038 | ||
1039 | template <typename Allocator, unsigned int Bits, typename Property> | |
1040 | struct query_member< | |
1041 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
1042 | Property, | |
1043 | typename boost::asio::enable_if< | |
1044 | boost::asio::is_convertible< | |
1045 | Property, | |
1046 | boost::asio::execution::blocking_t | |
1047 | >::value | |
1048 | >::type | |
1049 | > | |
1050 | { | |
1051 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1052 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
1053 | typedef boost::asio::execution::blocking_t result_type; | |
1054 | }; | |
1055 | ||
1056 | template <typename Allocator, unsigned int Bits, typename Property> | |
1057 | struct query_member< | |
1058 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
1059 | Property, | |
1060 | typename boost::asio::enable_if< | |
1061 | boost::asio::is_convertible< | |
1062 | Property, | |
1063 | boost::asio::execution::relationship_t | |
1064 | >::value | |
1065 | >::type | |
1066 | > | |
1067 | { | |
1068 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1069 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
1070 | typedef boost::asio::execution::relationship_t result_type; | |
1071 | }; | |
1072 | ||
1073 | template <typename Allocator, unsigned int Bits> | |
1074 | struct query_member< | |
1075 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
1076 | boost::asio::execution::occupancy_t | |
1077 | > | |
1078 | { | |
1079 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1080 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
1081 | typedef std::size_t result_type; | |
1082 | }; | |
1083 | ||
1084 | template <typename Allocator, unsigned int Bits> | |
1085 | struct query_member< | |
1086 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
1087 | boost::asio::execution::context_t | |
1088 | > | |
1089 | { | |
1090 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1091 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
1092 | typedef boost::asio::thread_pool& result_type; | |
1093 | }; | |
1094 | ||
1095 | template <typename Allocator, unsigned int Bits> | |
1096 | struct query_member< | |
1097 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
1098 | boost::asio::execution::allocator_t<void> | |
1099 | > | |
1100 | { | |
1101 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1102 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
1103 | typedef Allocator result_type; | |
1104 | }; | |
1105 | ||
1106 | template <typename Allocator, unsigned int Bits, typename OtherAllocator> | |
1107 | struct query_member< | |
1108 | boost::asio::thread_pool::basic_executor_type<Allocator, Bits>, | |
1109 | boost::asio::execution::allocator_t<OtherAllocator> | |
1110 | > | |
1111 | { | |
1112 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
1113 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
1114 | typedef Allocator result_type; | |
1115 | }; | |
1116 | ||
1117 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) | |
1118 | ||
1119 | } // namespace traits | |
1120 | ||
1e59de90 TL |
1121 | namespace execution { |
1122 | ||
1123 | template <> | |
1124 | struct is_executor<thread_pool> : false_type | |
1125 | { | |
1126 | }; | |
1127 | ||
1128 | } // namespace execution | |
1129 | ||
20effc67 TL |
1130 | #endif // !defined(GENERATING_DOCUMENTATION) |
1131 | ||
b32b8144 FG |
1132 | } // namespace asio |
1133 | } // namespace boost | |
1134 | ||
1135 | #include <boost/asio/detail/pop_options.hpp> | |
1136 | ||
1137 | #include <boost/asio/impl/thread_pool.hpp> | |
1138 | #if defined(BOOST_ASIO_HEADER_ONLY) | |
1139 | # include <boost/asio/impl/thread_pool.ipp> | |
1140 | #endif // defined(BOOST_ASIO_HEADER_ONLY) | |
1141 | ||
1142 | #endif // BOOST_ASIO_THREAD_POOL_HPP |