1 // 2 // detail/work_dispatcher.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2021 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_DETAIL_WORK_DISPATCHER_HPP 12 #define BOOST_ASIO_DETAIL_WORK_DISPATCHER_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/type_traits.hpp> 20 #include <boost/asio/associated_executor.hpp> 21 #include <boost/asio/associated_allocator.hpp> 22 #include <boost/asio/executor_work_guard.hpp> 23 #include <boost/asio/execution/executor.hpp> 24 #include <boost/asio/execution/allocator.hpp> 25 #include <boost/asio/execution/blocking.hpp> 26 #include <boost/asio/execution/outstanding_work.hpp> 27 #include <boost/asio/prefer.hpp> 28 29 #include <boost/asio/detail/push_options.hpp> 30 31 namespace boost { 32 namespace asio { 33 namespace detail { 34 35 template <typename Handler, typename Executor, typename = void> 36 struct is_work_dispatcher_required : true_type 37 { 38 }; 39 40 template <typename Handler, typename Executor> 41 struct is_work_dispatcher_required<Handler, Executor, 42 typename enable_if< 43 is_same< 44 typename associated_executor<Handler, 45 Executor>::asio_associated_executor_is_unspecialised, 46 void 47 >::value 48 >::type> : false_type 49 { 50 }; 51 52 template <typename Handler, typename Executor, typename = void> 53 class work_dispatcher 54 { 55 public: 56 template <typename CompletionHandler> work_dispatcher(BOOST_ASIO_MOVE_ARG (CompletionHandler)handler,const Executor & handler_ex)57 work_dispatcher(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler, 58 const Executor& handler_ex) 59 : handler_(BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler)), 60 executor_(boost::asio::prefer(handler_ex, 61 execution::outstanding_work.tracked)) 62 { 63 } 64 65 #if defined(BOOST_ASIO_HAS_MOVE) work_dispatcher(const work_dispatcher & other)66 work_dispatcher(const work_dispatcher& other) 67 : handler_(other.handler_), 68 executor_(other.executor_) 69 { 70 } 71 work_dispatcher(work_dispatcher && other)72 work_dispatcher(work_dispatcher&& other) 73 : handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)), 74 executor_(BOOST_ASIO_MOVE_CAST(work_executor_type)(other.executor_)) 75 { 76 } 77 #endif // defined(BOOST_ASIO_HAS_MOVE) 78 operator ()()79 void operator()() 80 { 81 execution::execute( 82 boost::asio::prefer(executor_, 83 execution::blocking.possibly, 84 execution::allocator((get_associated_allocator)(handler_))), 85 BOOST_ASIO_MOVE_CAST(Handler)(handler_)); 86 } 87 88 private: 89 typedef typename decay< 90 typename prefer_result<const Executor&, 91 execution::outstanding_work_t::tracked_t 92 >::type 93 >::type work_executor_type; 94 95 Handler handler_; 96 work_executor_type executor_; 97 }; 98 99 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS) 100 101 template <typename Handler, typename Executor> 102 class work_dispatcher<Handler, Executor, 103 typename enable_if<!execution::is_executor<Executor>::value>::type> 104 { 105 public: 106 template <typename CompletionHandler> work_dispatcher(BOOST_ASIO_MOVE_ARG (CompletionHandler)handler,const Executor & handler_ex)107 work_dispatcher(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler, 108 const Executor& handler_ex) 109 : work_(handler_ex), 110 handler_(BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler)) 111 { 112 } 113 114 #if defined(BOOST_ASIO_HAS_MOVE) work_dispatcher(const work_dispatcher & other)115 work_dispatcher(const work_dispatcher& other) 116 : work_(other.work_), 117 handler_(other.handler_) 118 { 119 } 120 work_dispatcher(work_dispatcher && other)121 work_dispatcher(work_dispatcher&& other) 122 : work_(BOOST_ASIO_MOVE_CAST(executor_work_guard<Executor>)(other.work_)), 123 handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)) 124 { 125 } 126 #endif // defined(BOOST_ASIO_HAS_MOVE) 127 operator ()()128 void operator()() 129 { 130 typename associated_allocator<Handler>::type alloc( 131 (get_associated_allocator)(handler_)); 132 work_.get_executor().dispatch( 133 BOOST_ASIO_MOVE_CAST(Handler)(handler_), alloc); 134 work_.reset(); 135 } 136 137 private: 138 executor_work_guard<Executor> work_; 139 Handler handler_; 140 }; 141 142 #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS) 143 144 } // namespace detail 145 } // namespace asio 146 } // namespace boost 147 148 #include <boost/asio/detail/pop_options.hpp> 149 150 #endif // BOOST_ASIO_DETAIL_WORK_DISPATCHER_HPP 151