|
||||
File indexing completed on 2025-01-18 09:29:08
0001 // 0002 // co_spawn.hpp 0003 // ~~~~~~~~~~~~ 0004 // 0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) 0006 // 0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying 0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 0009 // 0010 0011 #ifndef BOOST_ASIO_CO_SPAWN_HPP 0012 #define BOOST_ASIO_CO_SPAWN_HPP 0013 0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 0015 # pragma once 0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 0017 0018 #include <boost/asio/detail/config.hpp> 0019 0020 #if defined(BOOST_ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION) 0021 0022 #include <boost/asio/awaitable.hpp> 0023 #include <boost/asio/execution/executor.hpp> 0024 #include <boost/asio/execution_context.hpp> 0025 #include <boost/asio/is_executor.hpp> 0026 0027 #include <boost/asio/detail/push_options.hpp> 0028 0029 namespace boost { 0030 namespace asio { 0031 namespace detail { 0032 0033 template <typename T> 0034 struct awaitable_signature; 0035 0036 template <typename T, typename Executor> 0037 struct awaitable_signature<awaitable<T, Executor>> 0038 { 0039 typedef void type(std::exception_ptr, T); 0040 }; 0041 0042 template <typename Executor> 0043 struct awaitable_signature<awaitable<void, Executor>> 0044 { 0045 typedef void type(std::exception_ptr); 0046 }; 0047 0048 } // namespace detail 0049 0050 /// Spawn a new coroutined-based thread of execution. 0051 /** 0052 * @param ex The executor that will be used to schedule the new thread of 0053 * execution. 0054 * 0055 * @param a The boost::asio::awaitable object that is the result of calling the 0056 * coroutine's entry point function. 0057 * 0058 * @param token The @ref completion_token that will handle the notification that 0059 * the thread of execution has completed. The function signature of the 0060 * completion handler must be: 0061 * @code void handler(std::exception_ptr, T); @endcode 0062 * 0063 * @par Completion Signature 0064 * @code void(std::exception_ptr, T) @endcode 0065 * 0066 * @par Example 0067 * @code 0068 * boost::asio::awaitable<std::size_t> echo(tcp::socket socket) 0069 * { 0070 * std::size_t bytes_transferred = 0; 0071 * 0072 * try 0073 * { 0074 * char data[1024]; 0075 * for (;;) 0076 * { 0077 * std::size_t n = co_await socket.async_read_some( 0078 * boost::asio::buffer(data), boost::asio::use_awaitable); 0079 * 0080 * co_await boost::asio::async_write(socket, 0081 * boost::asio::buffer(data, n), boost::asio::use_awaitable); 0082 * 0083 * bytes_transferred += n; 0084 * } 0085 * } 0086 * catch (const std::exception&) 0087 * { 0088 * } 0089 * 0090 * co_return bytes_transferred; 0091 * } 0092 * 0093 * // ... 0094 * 0095 * boost::asio::co_spawn(my_executor, 0096 * echo(std::move(my_tcp_socket)), 0097 * [](std::exception_ptr e, std::size_t n) 0098 * { 0099 * std::cout << "transferred " << n << "\n"; 0100 * }); 0101 * @endcode 0102 * 0103 * @par Per-Operation Cancellation 0104 * The new thread of execution is created with a cancellation state that 0105 * supports @c cancellation_type::terminal values only. To change the 0106 * cancellation state, call boost::asio::this_coro::reset_cancellation_state. 0107 */ 0108 template <typename Executor, typename T, typename AwaitableExecutor, 0109 BOOST_ASIO_COMPLETION_TOKEN_FOR( 0110 void(std::exception_ptr, T)) CompletionToken 0111 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)> 0112 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE( 0113 CompletionToken, void(std::exception_ptr, T)) 0114 co_spawn(const Executor& ex, awaitable<T, AwaitableExecutor> a, 0115 CompletionToken&& token 0116 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor), 0117 constraint_t< 0118 (is_executor<Executor>::value || execution::is_executor<Executor>::value) 0119 && is_convertible<Executor, AwaitableExecutor>::value 0120 > = 0); 0121 0122 /// Spawn a new coroutined-based thread of execution. 0123 /** 0124 * @param ex The executor that will be used to schedule the new thread of 0125 * execution. 0126 * 0127 * @param a The boost::asio::awaitable object that is the result of calling the 0128 * coroutine's entry point function. 0129 * 0130 * @param token The @ref completion_token that will handle the notification that 0131 * the thread of execution has completed. The function signature of the 0132 * completion handler must be: 0133 * @code void handler(std::exception_ptr); @endcode 0134 * 0135 * @par Completion Signature 0136 * @code void(std::exception_ptr) @endcode 0137 * 0138 * @par Example 0139 * @code 0140 * boost::asio::awaitable<void> echo(tcp::socket socket) 0141 * { 0142 * try 0143 * { 0144 * char data[1024]; 0145 * for (;;) 0146 * { 0147 * std::size_t n = co_await socket.async_read_some( 0148 * boost::asio::buffer(data), boost::asio::use_awaitable); 0149 * 0150 * co_await boost::asio::async_write(socket, 0151 * boost::asio::buffer(data, n), boost::asio::use_awaitable); 0152 * } 0153 * } 0154 * catch (const std::exception& e) 0155 * { 0156 * std::cerr << "Exception: " << e.what() << "\n"; 0157 * } 0158 * } 0159 * 0160 * // ... 0161 * 0162 * boost::asio::co_spawn(my_executor, 0163 * echo(std::move(my_tcp_socket)), 0164 * boost::asio::detached); 0165 * @endcode 0166 * 0167 * @par Per-Operation Cancellation 0168 * The new thread of execution is created with a cancellation state that 0169 * supports @c cancellation_type::terminal values only. To change the 0170 * cancellation state, call boost::asio::this_coro::reset_cancellation_state. 0171 */ 0172 template <typename Executor, typename AwaitableExecutor, 0173 BOOST_ASIO_COMPLETION_TOKEN_FOR( 0174 void(std::exception_ptr)) CompletionToken 0175 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)> 0176 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE( 0177 CompletionToken, void(std::exception_ptr)) 0178 co_spawn(const Executor& ex, awaitable<void, AwaitableExecutor> a, 0179 CompletionToken&& token 0180 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor), 0181 constraint_t< 0182 (is_executor<Executor>::value || execution::is_executor<Executor>::value) 0183 && is_convertible<Executor, AwaitableExecutor>::value 0184 > = 0); 0185 0186 /// Spawn a new coroutined-based thread of execution. 0187 /** 0188 * @param ctx An execution context that will provide the executor to be used to 0189 * schedule the new thread of execution. 0190 * 0191 * @param a The boost::asio::awaitable object that is the result of calling the 0192 * coroutine's entry point function. 0193 * 0194 * @param token The @ref completion_token that will handle the notification that 0195 * the thread of execution has completed. The function signature of the 0196 * completion handler must be: 0197 * @code void handler(std::exception_ptr); @endcode 0198 * 0199 * @par Completion Signature 0200 * @code void(std::exception_ptr, T) @endcode 0201 * 0202 * @par Example 0203 * @code 0204 * boost::asio::awaitable<std::size_t> echo(tcp::socket socket) 0205 * { 0206 * std::size_t bytes_transferred = 0; 0207 * 0208 * try 0209 * { 0210 * char data[1024]; 0211 * for (;;) 0212 * { 0213 * std::size_t n = co_await socket.async_read_some( 0214 * boost::asio::buffer(data), boost::asio::use_awaitable); 0215 * 0216 * co_await boost::asio::async_write(socket, 0217 * boost::asio::buffer(data, n), boost::asio::use_awaitable); 0218 * 0219 * bytes_transferred += n; 0220 * } 0221 * } 0222 * catch (const std::exception&) 0223 * { 0224 * } 0225 * 0226 * co_return bytes_transferred; 0227 * } 0228 * 0229 * // ... 0230 * 0231 * boost::asio::co_spawn(my_io_context, 0232 * echo(std::move(my_tcp_socket)), 0233 * [](std::exception_ptr e, std::size_t n) 0234 * { 0235 * std::cout << "transferred " << n << "\n"; 0236 * }); 0237 * @endcode 0238 * 0239 * @par Per-Operation Cancellation 0240 * The new thread of execution is created with a cancellation state that 0241 * supports @c cancellation_type::terminal values only. To change the 0242 * cancellation state, call boost::asio::this_coro::reset_cancellation_state. 0243 */ 0244 template <typename ExecutionContext, typename T, typename AwaitableExecutor, 0245 BOOST_ASIO_COMPLETION_TOKEN_FOR( 0246 void(std::exception_ptr, T)) CompletionToken 0247 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( 0248 typename ExecutionContext::executor_type)> 0249 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE( 0250 CompletionToken, void(std::exception_ptr, T)) 0251 co_spawn(ExecutionContext& ctx, awaitable<T, AwaitableExecutor> a, 0252 CompletionToken&& token 0253 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN( 0254 typename ExecutionContext::executor_type), 0255 constraint_t< 0256 is_convertible<ExecutionContext&, execution_context&>::value 0257 && is_convertible<typename ExecutionContext::executor_type, 0258 AwaitableExecutor>::value 0259 > = 0); 0260 0261 /// Spawn a new coroutined-based thread of execution. 0262 /** 0263 * @param ctx An execution context that will provide the executor to be used to 0264 * schedule the new thread of execution. 0265 * 0266 * @param a The boost::asio::awaitable object that is the result of calling the 0267 * coroutine's entry point function. 0268 * 0269 * @param token The @ref completion_token that will handle the notification that 0270 * the thread of execution has completed. The function signature of the 0271 * completion handler must be: 0272 * @code void handler(std::exception_ptr); @endcode 0273 * 0274 * @par Completion Signature 0275 * @code void(std::exception_ptr) @endcode 0276 * 0277 * @par Example 0278 * @code 0279 * boost::asio::awaitable<void> echo(tcp::socket socket) 0280 * { 0281 * try 0282 * { 0283 * char data[1024]; 0284 * for (;;) 0285 * { 0286 * std::size_t n = co_await socket.async_read_some( 0287 * boost::asio::buffer(data), boost::asio::use_awaitable); 0288 * 0289 * co_await boost::asio::async_write(socket, 0290 * boost::asio::buffer(data, n), boost::asio::use_awaitable); 0291 * } 0292 * } 0293 * catch (const std::exception& e) 0294 * { 0295 * std::cerr << "Exception: " << e.what() << "\n"; 0296 * } 0297 * } 0298 * 0299 * // ... 0300 * 0301 * boost::asio::co_spawn(my_io_context, 0302 * echo(std::move(my_tcp_socket)), 0303 * boost::asio::detached); 0304 * @endcode 0305 * 0306 * @par Per-Operation Cancellation 0307 * The new thread of execution is created with a cancellation state that 0308 * supports @c cancellation_type::terminal values only. To change the 0309 * cancellation state, call boost::asio::this_coro::reset_cancellation_state. 0310 */ 0311 template <typename ExecutionContext, typename AwaitableExecutor, 0312 BOOST_ASIO_COMPLETION_TOKEN_FOR( 0313 void(std::exception_ptr)) CompletionToken 0314 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( 0315 typename ExecutionContext::executor_type)> 0316 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE( 0317 CompletionToken, void(std::exception_ptr)) 0318 co_spawn(ExecutionContext& ctx, awaitable<void, AwaitableExecutor> a, 0319 CompletionToken&& token 0320 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN( 0321 typename ExecutionContext::executor_type), 0322 constraint_t< 0323 is_convertible<ExecutionContext&, execution_context&>::value 0324 && is_convertible<typename ExecutionContext::executor_type, 0325 AwaitableExecutor>::value 0326 > = 0); 0327 0328 /// Spawn a new coroutined-based thread of execution. 0329 /** 0330 * @param ex The executor that will be used to schedule the new thread of 0331 * execution. 0332 * 0333 * @param f A nullary function object with a return type of the form 0334 * @c boost::asio::awaitable<R,E> that will be used as the coroutine's entry 0335 * point. 0336 * 0337 * @param token The @ref completion_token that will handle the notification 0338 * that the thread of execution has completed. If @c R is @c void, the function 0339 * signature of the completion handler must be: 0340 * 0341 * @code void handler(std::exception_ptr); @endcode 0342 * Otherwise, the function signature of the completion handler must be: 0343 * @code void handler(std::exception_ptr, R); @endcode 0344 * 0345 * @par Completion Signature 0346 * @code void(std::exception_ptr, R) @endcode 0347 * where @c R is the first template argument to the @c awaitable returned by the 0348 * supplied function object @c F: 0349 * @code boost::asio::awaitable<R, AwaitableExecutor> F() @endcode 0350 * 0351 * @par Example 0352 * @code 0353 * boost::asio::awaitable<std::size_t> echo(tcp::socket socket) 0354 * { 0355 * std::size_t bytes_transferred = 0; 0356 * 0357 * try 0358 * { 0359 * char data[1024]; 0360 * for (;;) 0361 * { 0362 * std::size_t n = co_await socket.async_read_some( 0363 * boost::asio::buffer(data), boost::asio::use_awaitable); 0364 * 0365 * co_await boost::asio::async_write(socket, 0366 * boost::asio::buffer(data, n), boost::asio::use_awaitable); 0367 * 0368 * bytes_transferred += n; 0369 * } 0370 * } 0371 * catch (const std::exception&) 0372 * { 0373 * } 0374 * 0375 * co_return bytes_transferred; 0376 * } 0377 * 0378 * // ... 0379 * 0380 * boost::asio::co_spawn(my_executor, 0381 * [socket = std::move(my_tcp_socket)]() mutable 0382 * -> boost::asio::awaitable<void> 0383 * { 0384 * try 0385 * { 0386 * char data[1024]; 0387 * for (;;) 0388 * { 0389 * std::size_t n = co_await socket.async_read_some( 0390 * boost::asio::buffer(data), boost::asio::use_awaitable); 0391 * 0392 * co_await boost::asio::async_write(socket, 0393 * boost::asio::buffer(data, n), boost::asio::use_awaitable); 0394 * } 0395 * } 0396 * catch (const std::exception& e) 0397 * { 0398 * std::cerr << "Exception: " << e.what() << "\n"; 0399 * } 0400 * }, boost::asio::detached); 0401 * @endcode 0402 * 0403 * @par Per-Operation Cancellation 0404 * The new thread of execution is created with a cancellation state that 0405 * supports @c cancellation_type::terminal values only. To change the 0406 * cancellation state, call boost::asio::this_coro::reset_cancellation_state. 0407 */ 0408 template <typename Executor, typename F, 0409 BOOST_ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature< 0410 result_of_t<F()>>::type) CompletionToken 0411 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)> 0412 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, 0413 typename detail::awaitable_signature<result_of_t<F()>>::type) 0414 co_spawn(const Executor& ex, F&& f, 0415 CompletionToken&& token 0416 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor), 0417 constraint_t< 0418 is_executor<Executor>::value || execution::is_executor<Executor>::value 0419 > = 0); 0420 0421 /// Spawn a new coroutined-based thread of execution. 0422 /** 0423 * @param ctx An execution context that will provide the executor to be used to 0424 * schedule the new thread of execution. 0425 * 0426 * @param f A nullary function object with a return type of the form 0427 * @c boost::asio::awaitable<R,E> that will be used as the coroutine's entry 0428 * point. 0429 * 0430 * @param token The @ref completion_token that will handle the notification 0431 * that the thread of execution has completed. If @c R is @c void, the function 0432 * signature of the completion handler must be: 0433 * 0434 * @code void handler(std::exception_ptr); @endcode 0435 * Otherwise, the function signature of the completion handler must be: 0436 * @code void handler(std::exception_ptr, R); @endcode 0437 * 0438 * @par Completion Signature 0439 * @code void(std::exception_ptr, R) @endcode 0440 * where @c R is the first template argument to the @c awaitable returned by the 0441 * supplied function object @c F: 0442 * @code boost::asio::awaitable<R, AwaitableExecutor> F() @endcode 0443 * 0444 * @par Example 0445 * @code 0446 * boost::asio::awaitable<std::size_t> echo(tcp::socket socket) 0447 * { 0448 * std::size_t bytes_transferred = 0; 0449 * 0450 * try 0451 * { 0452 * char data[1024]; 0453 * for (;;) 0454 * { 0455 * std::size_t n = co_await socket.async_read_some( 0456 * boost::asio::buffer(data), boost::asio::use_awaitable); 0457 * 0458 * co_await boost::asio::async_write(socket, 0459 * boost::asio::buffer(data, n), boost::asio::use_awaitable); 0460 * 0461 * bytes_transferred += n; 0462 * } 0463 * } 0464 * catch (const std::exception&) 0465 * { 0466 * } 0467 * 0468 * co_return bytes_transferred; 0469 * } 0470 * 0471 * // ... 0472 * 0473 * boost::asio::co_spawn(my_io_context, 0474 * [socket = std::move(my_tcp_socket)]() mutable 0475 * -> boost::asio::awaitable<void> 0476 * { 0477 * try 0478 * { 0479 * char data[1024]; 0480 * for (;;) 0481 * { 0482 * std::size_t n = co_await socket.async_read_some( 0483 * boost::asio::buffer(data), boost::asio::use_awaitable); 0484 * 0485 * co_await boost::asio::async_write(socket, 0486 * boost::asio::buffer(data, n), boost::asio::use_awaitable); 0487 * } 0488 * } 0489 * catch (const std::exception& e) 0490 * { 0491 * std::cerr << "Exception: " << e.what() << "\n"; 0492 * } 0493 * }, boost::asio::detached); 0494 * @endcode 0495 * 0496 * @par Per-Operation Cancellation 0497 * The new thread of execution is created with a cancellation state that 0498 * supports @c cancellation_type::terminal values only. To change the 0499 * cancellation state, call boost::asio::this_coro::reset_cancellation_state. 0500 */ 0501 template <typename ExecutionContext, typename F, 0502 BOOST_ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature< 0503 result_of_t<F()>>::type) CompletionToken 0504 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( 0505 typename ExecutionContext::executor_type)> 0506 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, 0507 typename detail::awaitable_signature<result_of_t<F()>>::type) 0508 co_spawn(ExecutionContext& ctx, F&& f, 0509 CompletionToken&& token 0510 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN( 0511 typename ExecutionContext::executor_type), 0512 constraint_t< 0513 is_convertible<ExecutionContext&, execution_context&>::value 0514 > = 0); 0515 0516 } // namespace asio 0517 } // namespace boost 0518 0519 #include <boost/asio/detail/pop_options.hpp> 0520 0521 #include <boost/asio/impl/co_spawn.hpp> 0522 0523 #endif // defined(BOOST_ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION) 0524 0525 #endif // BOOST_ASIO_CO_SPAWN_HPP
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |