1[/ 2 / Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) 3 / 4 / Distributed under the Boost Software License, Version 1.0. (See accompanying 5 / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 /] 7 8[section:std_executors Proposed Standard Executors] 9 10Boost.Asio provides a complete implementation of the proposed standard executors, as 11described in [@http://wg21.link/P0443r13 P0443r13], [@http://wg21.link/P1348r0 12P1348r0], and [@http://wg21.link/P1393r0 P1393r0]. 13 14Just as with executors under the Networking TS model, a standard executor 15represents a policy as to how, when, and where a piece of code should be 16executed. Most existing code should continue to work with little or no change. 17 18[heading Standard Executor Implementations in Boost.Asio] 19 20The [link boost_asio.reference.io_context.executor_type `io_context::executor_type`], 21[link boost_asio.reference.thread_pool.executor_type `thread_pool::executor_type`], 22[link boost_asio.reference.system_executor `system_executor`], and [link 23boost_asio.reference.strand `strand`] executors meet the requirements for the 24proposed standard executors. For compatibility, these classes also meet the 25requirements for the Networking TS model of executors. 26 27[heading Standard Executor Use in Boost.Asio] 28 29All I/O objects such as [link boost_asio.reference.ip__tcp.socket `ip::tcp::socket`], 30asynchronous operations, and utilities including [link boost_asio.reference.dispatch 31`dispatch`], [link boost_asio.reference.post `post`], [link boost_asio.reference.defer 32`defer`], [link boost_asio.reference.get_associated_executor 33`get_associated_executor`], [link boost_asio.reference.bind_executor 34`bind_executor`], [link boost_asio.reference.make_work_guard `make_work_guard`], 35[link boost_asio.reference.spawn `spawn`], [link boost_asio.reference.co_spawn `co_spawn`], 36[link boost_asio.reference.async_compose `async_compose`], [link 37boost_asio.reference.use_future `use_future`], etc., can interoperate with both 38proposed standard executors, and with Networking TS executors. Boost.Asio's 39implementation determines at compile time which model a particular executor 40meets; the proposed standard executor model is used in preference if both are 41detected. 42 43Support for the existing Networking TS model of executors can be disabled 44by defining `BOOST_ASIO_NO_TS_EXECUTORS`. 45 46[heading Polymorphic I/O Executor] 47 48The [link boost_asio.reference.any_io_executor `any_io_executor`] type alias is the 49default runtime-polymorphic executor for all I/O objects. This type alias 50points to the [link boost_asio.reference.execution__any_executor 51`execution::any_executor<>`] template with a set of supportable properties 52specified for use with I/O. 53 54This new name may break existing code that directly uses the old polymorphic 55wrapper, [link boost_asio.reference.executor `executor`]. If required for backward 56compatibility, `BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT` can be defined, which changes 57the `any_io_executor` type alias to instead point to the `executor` polymorphic 58wrapper. 59 60[heading Implementing a Minimal I/O Executor] 61 62Standard executor properties make what were previously hard requirements on an 63executor (such as work counting, or the ability to distinguish between `post`, 64`dispatch`, and `defer`) into optional facilities. With this relaxation, the 65minimal requirements for an I/O executor are: 66 67* Conformance to the [link boost_asio.reference.Executor1.standard_executors 68 `executor`] concept. 69 70* The ability to query the [link boost_asio.reference.execution__context 71 `execution::context`] property, with the result being [link 72 boost_asio.reference.execution_context `execution_context&`] or a reference to a 73 class that is derived from `execution_context`. 74 75* The `execute` operation having, at minimum, the [link 76 boost_asio.reference.execution__blocking_t.never `execution::blocking.never`] 77 semantic. 78 79The following example shows a minimal I/O executor. Given a queue submission 80operation implemented elsewhere: 81 82``` 83queue_t queue_create(); 84template <typename F> void queue_submit(queue_t q, F f); 85``` 86 87the executor may be defined as follows: 88 89``` 90struct minimal_io_executor 91{ 92 boost::asio::execution_context* context_; 93 queue_t queue_; 94 95 bool operator==(const minimal_io_executor& other) const noexcept 96 { 97 return context_ == other.context_ && queue_ == other.queue_; 98 } 99 100 bool operator!=(const minimal_io_executor& other) const noexcept 101 { 102 return !(*this == other); 103 } 104 105 boost::asio::execution_context& query( 106 boost::asio::execution::context_t) const noexcept 107 { 108 return *context_; 109 } 110 111 static constexpr boost::asio::execution::blocking_t::never_t query( 112 boost::asio::execution::blocking_t) noexcept 113 { 114 // This executor always has blocking.never semantics. 115 return boost::asio::execution::blocking.never; 116 } 117 118 template <class F> 119 void execute(F f) const 120 { 121 queue_submit(queue_, std::move(f)); 122 } 123}; 124``` 125 126This executor may be created as follows: 127 128``` 129boost::asio::execution_context context; 130queue_t queue = queue_create(); 131minimal_io_executor executor{&context, queue}; 132``` 133 134and then used with I/O objects: 135 136``` 137boost::asio::ip::tcp::acceptor acceptor(executor); 138``` 139 140or assigned into the [link boost_asio.reference.any_io_executor `any_io_executor`] 141polymorphic wrapper: 142 143``` 144boost::asio::any_io_executor poly_executor = executor; 145``` 146 147[heading Traits for Deducing Conformance to the Executor Concept] 148 149Older C++ standards and compilers require some assistance to determine whether 150an executor implementation conforms to the `executor` concept and type 151requirements. This is achieved through specialisation of traits. The following 152code shows a specialisation of these traits for the `minimal_io_executor` 153example from above: 154 155``` 156namespace boost { namespace asio { 157namespace traits { 158 159#if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) 160 161template <typename F> 162struct execute_member<minimal_io_executor, F> 163{ 164 static constexpr bool is_valid = true; 165 static constexpr bool is_noexcept = true; 166 typedef void result_type; 167}; 168 169#endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) 170#if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) 171 172template <> 173struct equality_comparable<minimal_io_executor> 174{ 175 static constexpr bool is_valid = true; 176 static constexpr bool is_noexcept = true; 177}; 178 179#endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) 180#if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) 181 182template <> 183struct query_member<minimal_io_executor, 184 boost::asio::execution::context_t> 185{ 186 static constexpr bool is_valid = true; 187 static constexpr bool is_noexcept = true; 188 typedef boost::asio::execution_context& result_type; 189}; 190 191#endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) 192#if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) 193 194template <typename Property> 195struct query_static_constexpr_member<minimal_io_executor, Property, 196 typename enable_if< 197 std::is_convertible<Property, boost::asio::execution::blocking_t>::value 198 >::type> 199{ 200 static constexpr bool is_valid = true; 201 static constexpr bool is_noexcept = true; 202 typedef boost::asio::execution::blocking_t::never_t result_type; 203 static constexpr result_type value() noexcept { return result_type(); } 204}; 205 206#endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) 207 208} // namespace traits 209} } // namespace boost::asio 210``` 211 212Boost.Asio uses an extensive set of traits to implement all of the proposed standard 213executor functionality on older C++ standards. These traits may be found under 214the [^boost/asio/traits] include directory. 215 216[endsect] 217