// // thread_pool.hpp // ~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef ASIO_THREAD_POOL_HPP #define ASIO_THREAD_POOL_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" #include "asio/detail/atomic_count.hpp" #include "asio/detail/scheduler.hpp" #include "asio/detail/thread_group.hpp" #include "asio/execution.hpp" #include "asio/execution_context.hpp" #include "asio/detail/push_options.hpp" namespace asio { namespace detail { struct thread_pool_bits { ASIO_STATIC_CONSTEXPR(unsigned int, blocking_never = 1); ASIO_STATIC_CONSTEXPR(unsigned int, blocking_always = 2); ASIO_STATIC_CONSTEXPR(unsigned int, blocking_mask = 3); ASIO_STATIC_CONSTEXPR(unsigned int, relationship_continuation = 4); ASIO_STATIC_CONSTEXPR(unsigned int, outstanding_work_tracked = 8); }; } // namespace detail /// A simple fixed-size thread pool. /** * The thread pool class is an execution context where functions are permitted * to run on one of a fixed number of threads. * * @par Submitting tasks to the pool * * To submit functions to the thread pool, use the @ref asio::dispatch, * @ref asio::post or @ref asio::defer free functions. * * For example: * * @code void my_task() * { * ... * } * * ... * * // Launch the pool with four threads. * asio::thread_pool pool(4); * * // Submit a function to the pool. * asio::post(pool, my_task); * * // Submit a lambda object to the pool. * asio::post(pool, * []() * { * ... * }); * * // Wait for all tasks in the pool to complete. * pool.join(); @endcode */ class thread_pool : public execution_context { public: template class basic_executor_type; template friend class basic_executor_type; /// Executor used to submit functions to a thread pool. typedef basic_executor_type, 0> executor_type; /// Scheduler used to schedule receivers on a thread pool. typedef basic_executor_type, 0> scheduler_type; #if !defined(ASIO_NO_TS_EXECUTORS) /// Constructs a pool with an automatically determined number of threads. ASIO_DECL thread_pool(); #endif // !defined(ASIO_NO_TS_EXECUTORS) /// Constructs a pool with a specified number of threads. ASIO_DECL thread_pool(std::size_t num_threads); /// Destructor. /** * Automatically stops and joins the pool, if not explicitly done beforehand. */ ASIO_DECL ~thread_pool(); /// Obtains the executor associated with the pool. executor_type get_executor() ASIO_NOEXCEPT; /// Obtains the executor associated with the pool. executor_type executor() ASIO_NOEXCEPT; /// Obtains the scheduler associated with the pool. scheduler_type scheduler() ASIO_NOEXCEPT; /// Stops the threads. /** * This function stops the threads as soon as possible. As a result of calling * @c stop(), pending function objects may be never be invoked. */ ASIO_DECL void stop(); /// Attaches the current thread to the pool. /** * This function attaches the current thread to the pool so that it may be * used for executing submitted function objects. Blocks the calling thread * until the pool is stopped or joined and has no outstanding work. */ ASIO_DECL void attach(); /// Joins the threads. /** * This function blocks until the threads in the pool have completed. If @c * stop() is not called prior to @c join(), the @c join() call will wait * until the pool has no more outstanding work. */ ASIO_DECL void join(); /// Waits for threads to complete. /** * This function blocks until the threads in the pool have completed. If @c * stop() is not called prior to @c wait(), the @c wait() call will wait * until the pool has no more outstanding work. */ ASIO_DECL void wait(); private: thread_pool(const thread_pool&) ASIO_DELETED; thread_pool& operator=(const thread_pool&) ASIO_DELETED; struct thread_function; // Helper function to create the underlying scheduler. ASIO_DECL detail::scheduler& add_scheduler(detail::scheduler* s); // The underlying scheduler. detail::scheduler& scheduler_; // The threads in the pool. detail::thread_group threads_; // The current number of threads in the pool. detail::atomic_count num_threads_; }; /// Executor implementation type used to submit functions to a thread pool. template class thread_pool::basic_executor_type : detail::thread_pool_bits { public: /// The sender type, when this type is used as a scheduler. typedef basic_executor_type sender_type; /// The bulk execution shape type. typedef std::size_t shape_type; /// The bulk execution index type. typedef std::size_t index_type; #if defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) \ && defined(ASIO_HAS_STD_EXCEPTION_PTR) template < template class Tuple, template class Variant> using value_types = Variant>; template