1// 2// impl/thread_pool.ipp 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_IMPL_THREAD_POOL_IPP 12#define BOOST_ASIO_IMPL_THREAD_POOL_IPP 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 <stdexcept> 20#include <boost/asio/thread_pool.hpp> 21#include <boost/asio/detail/throw_exception.hpp> 22 23#include <boost/asio/detail/push_options.hpp> 24 25namespace boost { 26namespace asio { 27 28struct thread_pool::thread_function 29{ 30 detail::scheduler* scheduler_; 31 32 void operator()() 33 { 34#if !defined(BOOST_ASIO_NO_EXCEPTIONS) 35 try 36 { 37#endif// !defined(BOOST_ASIO_NO_EXCEPTIONS) 38 boost::system::error_code ec; 39 scheduler_->run(ec); 40#if !defined(BOOST_ASIO_NO_EXCEPTIONS) 41 } 42 catch (...) 43 { 44 std::terminate(); 45 } 46#endif// !defined(BOOST_ASIO_NO_EXCEPTIONS) 47 } 48}; 49 50#if !defined(BOOST_ASIO_NO_TS_EXECUTORS) 51namespace detail { 52 53inline long default_thread_pool_size() 54{ 55 std::size_t num_threads = thread::hardware_concurrency() * 2; 56 num_threads = num_threads == 0 ? 2 : num_threads; 57 return static_cast<long>(num_threads); 58} 59 60} // namespace detail 61 62thread_pool::thread_pool() 63 : scheduler_(add_scheduler(new detail::scheduler(*this, 0, false))), 64 num_threads_(detail::default_thread_pool_size()) 65{ 66 scheduler_.work_started(); 67 68 thread_function f = { &scheduler_ }; 69 threads_.create_threads(f, static_cast<std::size_t>(num_threads_)); 70} 71#endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS) 72 73namespace detail { 74 75inline long clamp_thread_pool_size(std::size_t n) 76{ 77 if (n > 0x7FFFFFFF) 78 { 79 std::out_of_range ex("thread pool size"); 80 boost::asio::detail::throw_exception(ex); 81 } 82 return static_cast<long>(n & 0x7FFFFFFF); 83} 84 85} // namespace detail 86 87thread_pool::thread_pool(std::size_t num_threads) 88 : scheduler_(add_scheduler(new detail::scheduler( 89 *this, num_threads == 1 ? 1 : 0, false))), 90 num_threads_(detail::clamp_thread_pool_size(num_threads)) 91{ 92 scheduler_.work_started(); 93 94 thread_function f = { &scheduler_ }; 95 threads_.create_threads(f, static_cast<std::size_t>(num_threads_)); 96} 97 98thread_pool::~thread_pool() 99{ 100 stop(); 101 join(); 102} 103 104void thread_pool::stop() 105{ 106 scheduler_.stop(); 107} 108 109void thread_pool::attach() 110{ 111 ++num_threads_; 112 thread_function f = { &scheduler_ }; 113 f(); 114} 115 116void thread_pool::join() 117{ 118 if (!threads_.empty()) 119 { 120 scheduler_.work_finished(); 121 threads_.join(); 122 } 123} 124 125detail::scheduler& thread_pool::add_scheduler(detail::scheduler* s) 126{ 127 detail::scoped_ptr<detail::scheduler> scoped_impl(s); 128 boost::asio::add_service<detail::scheduler>(*this, scoped_impl.get()); 129 return *scoped_impl.release(); 130} 131 132void thread_pool::wait() 133{ 134 scheduler_.work_finished(); 135 threads_.join(); 136} 137 138} // namespace asio 139} // namespace boost 140 141#include <boost/asio/detail/pop_options.hpp> 142 143#endif // BOOST_ASIO_IMPL_THREAD_POOL_IPP 144