![]() |
|
|||
File indexing completed on 2025-07-05 08:27:43
0001 // 0002 // spawn.hpp 0003 // ~~~~~~~~~ 0004 // 0005 // Copyright (c) 2003-2024 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_SPAWN_HPP 0012 #define BOOST_ASIO_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 #include <boost/asio/any_io_executor.hpp> 0020 #include <boost/asio/cancellation_signal.hpp> 0021 #include <boost/asio/cancellation_state.hpp> 0022 #include <boost/asio/detail/exception.hpp> 0023 #include <boost/asio/detail/memory.hpp> 0024 #include <boost/asio/detail/type_traits.hpp> 0025 #include <boost/asio/io_context.hpp> 0026 #include <boost/asio/is_executor.hpp> 0027 #include <boost/asio/strand.hpp> 0028 0029 #if defined(BOOST_ASIO_HAS_BOOST_COROUTINE) 0030 # include <boost/coroutine/all.hpp> 0031 #endif // defined(BOOST_ASIO_HAS_BOOST_COROUTINE) 0032 0033 #include <boost/asio/detail/push_options.hpp> 0034 0035 namespace boost { 0036 namespace asio { 0037 namespace detail { 0038 0039 // Base class for all spawn()-ed thread implementations. 0040 class spawned_thread_base 0041 { 0042 public: 0043 spawned_thread_base() 0044 : owner_(0), 0045 has_context_switched_(false), 0046 throw_if_cancelled_(false), 0047 terminal_(false) 0048 { 0049 } 0050 0051 virtual ~spawned_thread_base() {} 0052 virtual void resume() = 0; 0053 virtual void suspend_with(void (*fn)(void*), void* arg) = 0; 0054 virtual void destroy() = 0; 0055 0056 void attach(spawned_thread_base** owner) 0057 { 0058 owner_ = owner; 0059 *owner_ = this; 0060 } 0061 0062 void detach() 0063 { 0064 if (owner_) 0065 *owner_ = 0; 0066 owner_ = 0; 0067 } 0068 0069 void suspend() 0070 { 0071 suspend_with(0, 0); 0072 } 0073 0074 template <typename F> 0075 void suspend_with(F f) 0076 { 0077 suspend_with(&spawned_thread_base::call<F>, &f); 0078 } 0079 0080 cancellation_slot get_cancellation_slot() const noexcept 0081 { 0082 return cancellation_state_.slot(); 0083 } 0084 0085 cancellation_state get_cancellation_state() const noexcept 0086 { 0087 return cancellation_state_; 0088 } 0089 0090 void reset_cancellation_state() 0091 { 0092 cancellation_state_ = cancellation_state(parent_cancellation_slot_); 0093 } 0094 0095 template <typename Filter> 0096 void reset_cancellation_state(Filter filter) 0097 { 0098 cancellation_state_ = cancellation_state( 0099 parent_cancellation_slot_, filter, filter); 0100 } 0101 0102 template <typename InFilter, typename OutFilter> 0103 void reset_cancellation_state(InFilter in_filter, OutFilter out_filter) 0104 { 0105 cancellation_state_ = cancellation_state( 0106 parent_cancellation_slot_, in_filter, out_filter); 0107 } 0108 0109 cancellation_type_t cancelled() const noexcept 0110 { 0111 return cancellation_state_.cancelled(); 0112 } 0113 0114 bool has_context_switched() const noexcept 0115 { 0116 return has_context_switched_; 0117 } 0118 0119 bool throw_if_cancelled() const noexcept 0120 { 0121 return throw_if_cancelled_; 0122 } 0123 0124 void throw_if_cancelled(bool value) noexcept 0125 { 0126 throw_if_cancelled_ = value; 0127 } 0128 0129 protected: 0130 spawned_thread_base** owner_; // Points to data member in active handler. 0131 boost::asio::cancellation_slot parent_cancellation_slot_; 0132 boost::asio::cancellation_state cancellation_state_; 0133 bool has_context_switched_; 0134 bool throw_if_cancelled_; 0135 bool terminal_; 0136 0137 private: 0138 // Disallow copying and assignment. 0139 spawned_thread_base(const spawned_thread_base&) = delete; 0140 spawned_thread_base& operator=(const spawned_thread_base&) = delete; 0141 0142 template <typename F> 0143 static void call(void* f) 0144 { 0145 (*static_cast<F*>(f))(); 0146 } 0147 }; 0148 0149 template <typename T> 0150 struct spawn_signature 0151 { 0152 typedef void type(exception_ptr, T); 0153 }; 0154 0155 template <> 0156 struct spawn_signature<void> 0157 { 0158 typedef void type(exception_ptr); 0159 }; 0160 0161 template <typename Executor> 0162 class initiate_spawn; 0163 0164 } // namespace detail 0165 0166 /// A @ref completion_token that represents the currently executing coroutine. 0167 /** 0168 * The basic_yield_context class is a completion token type that is used to 0169 * represent the currently executing stackful coroutine. A basic_yield_context 0170 * object may be passed as a completion token to an asynchronous operation. For 0171 * example: 0172 * 0173 * @code template <typename Executor> 0174 * void my_coroutine(basic_yield_context<Executor> yield) 0175 * { 0176 * ... 0177 * std::size_t n = my_socket.async_read_some(buffer, yield); 0178 * ... 0179 * } @endcode 0180 * 0181 * The initiating function (async_read_some in the above example) suspends the 0182 * current coroutine. The coroutine is resumed when the asynchronous operation 0183 * completes, and the result of the operation is returned. 0184 */ 0185 template <typename Executor> 0186 class basic_yield_context 0187 { 0188 public: 0189 /// The executor type associated with the yield context. 0190 typedef Executor executor_type; 0191 0192 /// The cancellation slot type associated with the yield context. 0193 typedef cancellation_slot cancellation_slot_type; 0194 0195 /// Construct a yield context from another yield context type. 0196 /** 0197 * Requires that OtherExecutor be convertible to Executor. 0198 */ 0199 template <typename OtherExecutor> 0200 basic_yield_context(const basic_yield_context<OtherExecutor>& other, 0201 constraint_t< 0202 is_convertible<OtherExecutor, Executor>::value 0203 > = 0) 0204 : spawned_thread_(other.spawned_thread_), 0205 executor_(other.executor_), 0206 ec_(other.ec_) 0207 { 0208 } 0209 0210 /// Get the executor associated with the yield context. 0211 executor_type get_executor() const noexcept 0212 { 0213 return executor_; 0214 } 0215 0216 /// Get the cancellation slot associated with the coroutine. 0217 cancellation_slot_type get_cancellation_slot() const noexcept 0218 { 0219 return spawned_thread_->get_cancellation_slot(); 0220 } 0221 0222 /// Get the cancellation state associated with the coroutine. 0223 cancellation_state get_cancellation_state() const noexcept 0224 { 0225 return spawned_thread_->get_cancellation_state(); 0226 } 0227 0228 /// Reset the cancellation state associated with the coroutine. 0229 /** 0230 * Let <tt>P</tt> be the cancellation slot associated with the current 0231 * coroutine's @ref spawn completion handler. Assigns a new 0232 * boost::asio::cancellation_state object <tt>S</tt>, constructed as 0233 * <tt>S(P)</tt>, into the current coroutine's cancellation state object. 0234 */ 0235 void reset_cancellation_state() const 0236 { 0237 spawned_thread_->reset_cancellation_state(); 0238 } 0239 0240 /// Reset the cancellation state associated with the coroutine. 0241 /** 0242 * Let <tt>P</tt> be the cancellation slot associated with the current 0243 * coroutine's @ref spawn completion handler. Assigns a new 0244 * boost::asio::cancellation_state object <tt>S</tt>, constructed as <tt>S(P, 0245 * std::forward<Filter>(filter))</tt>, into the current coroutine's 0246 * cancellation state object. 0247 */ 0248 template <typename Filter> 0249 void reset_cancellation_state(Filter&& filter) const 0250 { 0251 spawned_thread_->reset_cancellation_state( 0252 static_cast<Filter&&>(filter)); 0253 } 0254 0255 /// Reset the cancellation state associated with the coroutine. 0256 /** 0257 * Let <tt>P</tt> be the cancellation slot associated with the current 0258 * coroutine's @ref spawn completion handler. Assigns a new 0259 * boost::asio::cancellation_state object <tt>S</tt>, constructed as <tt>S(P, 0260 * std::forward<InFilter>(in_filter), 0261 * std::forward<OutFilter>(out_filter))</tt>, into the current coroutine's 0262 * cancellation state object. 0263 */ 0264 template <typename InFilter, typename OutFilter> 0265 void reset_cancellation_state(InFilter&& in_filter, 0266 OutFilter&& out_filter) const 0267 { 0268 spawned_thread_->reset_cancellation_state( 0269 static_cast<InFilter&&>(in_filter), 0270 static_cast<OutFilter&&>(out_filter)); 0271 } 0272 0273 /// Determine whether the current coroutine has been cancelled. 0274 cancellation_type_t cancelled() const noexcept 0275 { 0276 return spawned_thread_->cancelled(); 0277 } 0278 0279 /// Determine whether the coroutine throws if trying to suspend when it has 0280 /// been cancelled. 0281 bool throw_if_cancelled() const noexcept 0282 { 0283 return spawned_thread_->throw_if_cancelled(); 0284 } 0285 0286 /// Set whether the coroutine throws if trying to suspend when it has been 0287 /// cancelled. 0288 void throw_if_cancelled(bool value) const noexcept 0289 { 0290 spawned_thread_->throw_if_cancelled(value); 0291 } 0292 0293 /// Return a yield context that sets the specified error_code. 0294 /** 0295 * By default, when a yield context is used with an asynchronous operation, a 0296 * non-success error_code is converted to system_error and thrown. This 0297 * operator may be used to specify an error_code object that should instead be 0298 * set with the asynchronous operation's result. For example: 0299 * 0300 * @code template <typename Executor> 0301 * void my_coroutine(basic_yield_context<Executor> yield) 0302 * { 0303 * ... 0304 * std::size_t n = my_socket.async_read_some(buffer, yield[ec]); 0305 * if (ec) 0306 * { 0307 * // An error occurred. 0308 * } 0309 * ... 0310 * } @endcode 0311 */ 0312 basic_yield_context operator[](boost::system::error_code& ec) const 0313 { 0314 basic_yield_context tmp(*this); 0315 tmp.ec_ = &ec; 0316 return tmp; 0317 } 0318 0319 #if !defined(GENERATING_DOCUMENTATION) 0320 //private: 0321 basic_yield_context(detail::spawned_thread_base* spawned_thread, 0322 const Executor& ex) 0323 : spawned_thread_(spawned_thread), 0324 executor_(ex), 0325 ec_(0) 0326 { 0327 } 0328 0329 detail::spawned_thread_base* spawned_thread_; 0330 Executor executor_; 0331 boost::system::error_code* ec_; 0332 #endif // !defined(GENERATING_DOCUMENTATION) 0333 }; 0334 0335 /// A @ref completion_token object that represents the currently executing 0336 /// coroutine. 0337 typedef basic_yield_context<any_io_executor> yield_context; 0338 0339 /** 0340 * @defgroup spawn boost::asio::spawn 0341 * 0342 * @brief Start a new stackful coroutine. 0343 * 0344 * The spawn() function is a high-level wrapper over the Boost.Coroutine 0345 * library. This function enables programs to implement asynchronous logic in a 0346 * synchronous manner, as illustrated by the following example: 0347 * 0348 * @code boost::asio::spawn(my_strand, do_echo, boost::asio::detached); 0349 * 0350 * // ... 0351 * 0352 * void do_echo(boost::asio::yield_context yield) 0353 * { 0354 * try 0355 * { 0356 * char data[128]; 0357 * for (;;) 0358 * { 0359 * std::size_t length = 0360 * my_socket.async_read_some( 0361 * boost::asio::buffer(data), yield); 0362 * 0363 * boost::asio::async_write(my_socket, 0364 * boost::asio::buffer(data, length), yield); 0365 * } 0366 * } 0367 * catch (std::exception& e) 0368 * { 0369 * // ... 0370 * } 0371 * } @endcode 0372 */ 0373 /*@{*/ 0374 0375 /// Start a new stackful coroutine that executes on a given executor. 0376 /** 0377 * This function is used to launch a new stackful coroutine. 0378 * 0379 * @param ex Identifies the executor that will run the stackful coroutine. 0380 * 0381 * @param function The coroutine function. The function must be callable the 0382 * signature: 0383 * @code void function(basic_yield_context<Executor> yield); @endcode 0384 * 0385 * @param token The @ref completion_token that will handle the notification 0386 * that the coroutine has completed. If the return type @c R of @c function is 0387 * @c void, the function signature of the completion handler must be: 0388 * 0389 * @code void handler(std::exception_ptr); @endcode 0390 * Otherwise, the function signature of the completion handler must be: 0391 * @code void handler(std::exception_ptr, R); @endcode 0392 * 0393 * @par Completion Signature 0394 * @code void(std::exception_ptr, R) @endcode 0395 * where @c R is the return type of the function object. 0396 * 0397 * @par Per-Operation Cancellation 0398 * The new thread of execution is created with a cancellation state that 0399 * supports @c cancellation_type::terminal values only. To change the 0400 * cancellation state, call the basic_yield_context member function 0401 * @c reset_cancellation_state. 0402 */ 0403 template <typename Executor, typename F, 0404 BOOST_ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature< 0405 result_of_t<F(basic_yield_context<Executor>)>>::type) 0406 CompletionToken = default_completion_token_t<Executor>> 0407 auto spawn(const Executor& ex, F&& function, 0408 CompletionToken&& token = default_completion_token_t<Executor>(), 0409 #if defined(BOOST_ASIO_HAS_BOOST_COROUTINE) 0410 constraint_t< 0411 !is_same< 0412 decay_t<CompletionToken>, 0413 boost::coroutines::attributes 0414 >::value 0415 > = 0, 0416 #endif // defined(BOOST_ASIO_HAS_BOOST_COROUTINE) 0417 constraint_t< 0418 is_executor<Executor>::value || execution::is_executor<Executor>::value 0419 > = 0) 0420 -> decltype( 0421 async_initiate<CompletionToken, 0422 typename detail::spawn_signature< 0423 result_of_t<F(basic_yield_context<Executor>)>>::type>( 0424 declval<detail::initiate_spawn<Executor>>(), 0425 token, static_cast<F&&>(function))); 0426 0427 /// Start a new stackful coroutine that executes on a given execution context. 0428 /** 0429 * This function is used to launch a new stackful coroutine. 0430 * 0431 * @param ctx Identifies the execution context that will run the stackful 0432 * coroutine. 0433 * 0434 * @param function The coroutine function. The function must be callable the 0435 * signature: 0436 * @code void function(basic_yield_context<Executor> yield); @endcode 0437 * 0438 * @param token The @ref completion_token that will handle the notification 0439 * that the coroutine has completed. If the return type @c R of @c function is 0440 * @c void, the function signature of the completion handler must be: 0441 * 0442 * @code void handler(std::exception_ptr); @endcode 0443 * Otherwise, the function signature of the completion handler must be: 0444 * @code void handler(std::exception_ptr, R); @endcode 0445 * 0446 * @par Completion Signature 0447 * @code void(std::exception_ptr, R) @endcode 0448 * where @c R is the return type of the function object. 0449 * 0450 * @par Per-Operation Cancellation 0451 * The new thread of execution is created with a cancellation state that 0452 * supports @c cancellation_type::terminal values only. To change the 0453 * cancellation state, call the basic_yield_context member function 0454 * @c reset_cancellation_state. 0455 */ 0456 template <typename ExecutionContext, typename F, 0457 BOOST_ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature< 0458 result_of_t<F(basic_yield_context< 0459 typename ExecutionContext::executor_type>)>>::type) 0460 CompletionToken = default_completion_token_t< 0461 typename ExecutionContext::executor_type>> 0462 auto spawn(ExecutionContext& ctx, F&& function, 0463 CompletionToken&& token 0464 = default_completion_token_t<typename ExecutionContext::executor_type>(), 0465 #if defined(BOOST_ASIO_HAS_BOOST_COROUTINE) 0466 constraint_t< 0467 !is_same< 0468 decay_t<CompletionToken>, 0469 boost::coroutines::attributes 0470 >::value 0471 > = 0, 0472 #endif // defined(BOOST_ASIO_HAS_BOOST_COROUTINE) 0473 constraint_t< 0474 is_convertible<ExecutionContext&, execution_context&>::value 0475 > = 0) 0476 -> decltype( 0477 async_initiate<CompletionToken, 0478 typename detail::spawn_signature< 0479 result_of_t<F(basic_yield_context< 0480 typename ExecutionContext::executor_type>)>>::type>( 0481 declval<detail::initiate_spawn< 0482 typename ExecutionContext::executor_type>>(), 0483 token, static_cast<F&&>(function))); 0484 0485 /// Start a new stackful coroutine, inheriting the executor of another. 0486 /** 0487 * This function is used to launch a new stackful coroutine. 0488 * 0489 * @param ctx Identifies the current coroutine as a parent of the new 0490 * coroutine. This specifies that the new coroutine should inherit the executor 0491 * of the parent. For example, if the parent coroutine is executing in a 0492 * particular strand, then the new coroutine will execute in the same strand. 0493 * 0494 * @param function The coroutine function. The function must be callable the 0495 * signature: 0496 * @code void function(basic_yield_context<Executor> yield); @endcode 0497 * 0498 * @param token The @ref completion_token that will handle the notification 0499 * that the coroutine has completed. If the return type @c R of @c function is 0500 * @c void, the function signature of the completion handler must be: 0501 * 0502 * @code void handler(std::exception_ptr); @endcode 0503 * Otherwise, the function signature of the completion handler must be: 0504 * @code void handler(std::exception_ptr, R); @endcode 0505 * 0506 * @par Completion Signature 0507 * @code void(std::exception_ptr, R) @endcode 0508 * where @c R is the return type of the function object. 0509 * 0510 * @par Per-Operation Cancellation 0511 * The new thread of execution is created with a cancellation state that 0512 * supports @c cancellation_type::terminal values only. To change the 0513 * cancellation state, call the basic_yield_context member function 0514 * @c reset_cancellation_state. 0515 */ 0516 template <typename Executor, typename F, 0517 BOOST_ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature< 0518 result_of_t<F(basic_yield_context<Executor>)>>::type) 0519 CompletionToken = default_completion_token_t<Executor>> 0520 auto spawn(const basic_yield_context<Executor>& ctx, F&& function, 0521 CompletionToken&& token = default_completion_token_t<Executor>(), 0522 #if defined(BOOST_ASIO_HAS_BOOST_COROUTINE) 0523 constraint_t< 0524 !is_same< 0525 decay_t<CompletionToken>, 0526 boost::coroutines::attributes 0527 >::value 0528 > = 0, 0529 #endif // defined(BOOST_ASIO_HAS_BOOST_COROUTINE) 0530 constraint_t< 0531 is_executor<Executor>::value || execution::is_executor<Executor>::value 0532 > = 0) 0533 -> decltype( 0534 async_initiate<CompletionToken, 0535 typename detail::spawn_signature< 0536 result_of_t<F(basic_yield_context<Executor>)>>::type>( 0537 declval<detail::initiate_spawn<Executor>>(), 0538 token, static_cast<F&&>(function))); 0539 0540 #if defined(BOOST_ASIO_HAS_BOOST_CONTEXT_FIBER) \ 0541 || defined(GENERATING_DOCUMENTATION) 0542 0543 /// Start a new stackful coroutine that executes on a given executor. 0544 /** 0545 * This function is used to launch a new stackful coroutine using the 0546 * specified stack allocator. 0547 * 0548 * @param ex Identifies the executor that will run the stackful coroutine. 0549 * 0550 * @param stack_allocator Denotes the allocator to be used to allocate the 0551 * underlying coroutine's stack. The type must satisfy the stack-allocator 0552 * concept defined by the Boost.Context library. 0553 * 0554 * @param function The coroutine function. The function must be callable the 0555 * signature: 0556 * @code void function(basic_yield_context<Executor> yield); @endcode 0557 * 0558 * @param token The @ref completion_token that will handle the notification 0559 * that the coroutine has completed. If the return type @c R of @c function is 0560 * @c void, the function signature of the completion handler must be: 0561 * 0562 * @code void handler(std::exception_ptr); @endcode 0563 * Otherwise, the function signature of the completion handler must be: 0564 * @code void handler(std::exception_ptr, R); @endcode 0565 * 0566 * @par Completion Signature 0567 * @code void(std::exception_ptr, R) @endcode 0568 * where @c R is the return type of the function object. 0569 * 0570 * @par Per-Operation Cancellation 0571 * The new thread of execution is created with a cancellation state that 0572 * supports @c cancellation_type::terminal values only. To change the 0573 * cancellation state, call the basic_yield_context member function 0574 * @c reset_cancellation_state. 0575 */ 0576 template <typename Executor, typename StackAllocator, typename F, 0577 BOOST_ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature< 0578 result_of_t<F(basic_yield_context<Executor>)>>::type) 0579 CompletionToken = default_completion_token_t<Executor>> 0580 auto spawn(const Executor& ex, allocator_arg_t, 0581 StackAllocator&& stack_allocator, F&& function, 0582 CompletionToken&& token = default_completion_token_t<Executor>(), 0583 constraint_t< 0584 is_executor<Executor>::value || execution::is_executor<Executor>::value 0585 > = 0) 0586 -> decltype( 0587 async_initiate<CompletionToken, 0588 typename detail::spawn_signature< 0589 result_of_t<F(basic_yield_context<Executor>)>>::type>( 0590 declval<detail::initiate_spawn<Executor>>(), 0591 token, allocator_arg_t(), 0592 static_cast<StackAllocator&&>(stack_allocator), 0593 static_cast<F&&>(function))); 0594 0595 /// Start a new stackful coroutine that executes on a given execution context. 0596 /** 0597 * This function is used to launch a new stackful coroutine. 0598 * 0599 * @param ctx Identifies the execution context that will run the stackful 0600 * coroutine. 0601 * 0602 * @param stack_allocator Denotes the allocator to be used to allocate the 0603 * underlying coroutine's stack. The type must satisfy the stack-allocator 0604 * concept defined by the Boost.Context library. 0605 * 0606 * @param function The coroutine function. The function must be callable the 0607 * signature: 0608 * @code void function(basic_yield_context<Executor> yield); @endcode 0609 * 0610 * @param token The @ref completion_token that will handle the notification 0611 * that the coroutine has completed. If the return type @c R of @c function is 0612 * @c void, the function signature of the completion handler must be: 0613 * 0614 * @code void handler(std::exception_ptr); @endcode 0615 * Otherwise, the function signature of the completion handler must be: 0616 * @code void handler(std::exception_ptr, R); @endcode 0617 * 0618 * @par Completion Signature 0619 * @code void(std::exception_ptr, R) @endcode 0620 * where @c R is the return type of the function object. 0621 * 0622 * @par Per-Operation Cancellation 0623 * The new thread of execution is created with a cancellation state that 0624 * supports @c cancellation_type::terminal values only. To change the 0625 * cancellation state, call the basic_yield_context member function 0626 * @c reset_cancellation_state. 0627 */ 0628 template <typename ExecutionContext, typename StackAllocator, typename F, 0629 BOOST_ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature< 0630 result_of_t<F(basic_yield_context< 0631 typename ExecutionContext::executor_type>)>>::type) 0632 CompletionToken = default_completion_token_t< 0633 typename ExecutionContext::executor_type>> 0634 auto spawn(ExecutionContext& ctx, allocator_arg_t, 0635 StackAllocator&& stack_allocator, F&& function, 0636 CompletionToken&& token 0637 = default_completion_token_t<typename ExecutionContext::executor_type>(), 0638 constraint_t< 0639 is_convertible<ExecutionContext&, execution_context&>::value 0640 > = 0) 0641 -> decltype( 0642 async_initiate<CompletionToken, 0643 typename detail::spawn_signature< 0644 result_of_t<F(basic_yield_context< 0645 typename ExecutionContext::executor_type>)>>::type>( 0646 declval<detail::initiate_spawn< 0647 typename ExecutionContext::executor_type>>(), 0648 token, allocator_arg_t(), 0649 static_cast<StackAllocator&&>(stack_allocator), 0650 static_cast<F&&>(function))); 0651 0652 /// Start a new stackful coroutine, inheriting the executor of another. 0653 /** 0654 * This function is used to launch a new stackful coroutine using the 0655 * specified stack allocator. 0656 * 0657 * @param ctx Identifies the current coroutine as a parent of the new 0658 * coroutine. This specifies that the new coroutine should inherit the 0659 * executor of the parent. For example, if the parent coroutine is executing 0660 * in a particular strand, then the new coroutine will execute in the same 0661 * strand. 0662 * 0663 * @param stack_allocator Denotes the allocator to be used to allocate the 0664 * underlying coroutine's stack. The type must satisfy the stack-allocator 0665 * concept defined by the Boost.Context library. 0666 * 0667 * @param function The coroutine function. The function must be callable the 0668 * signature: 0669 * @code void function(basic_yield_context<Executor> yield); @endcode 0670 * 0671 * @param token The @ref completion_token that will handle the notification 0672 * that the coroutine has completed. If the return type @c R of @c function is 0673 * @c void, the function signature of the completion handler must be: 0674 * 0675 * @code void handler(std::exception_ptr); @endcode 0676 * Otherwise, the function signature of the completion handler must be: 0677 * @code void handler(std::exception_ptr, R); @endcode 0678 * 0679 * @par Completion Signature 0680 * @code void(std::exception_ptr, R) @endcode 0681 * where @c R is the return type of the function object. 0682 * 0683 * @par Per-Operation Cancellation 0684 * The new thread of execution is created with a cancellation state that 0685 * supports @c cancellation_type::terminal values only. To change the 0686 * cancellation state, call the basic_yield_context member function 0687 * @c reset_cancellation_state. 0688 */ 0689 template <typename Executor, typename StackAllocator, typename F, 0690 BOOST_ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature< 0691 result_of_t<F(basic_yield_context<Executor>)>>::type) 0692 CompletionToken = default_completion_token_t<Executor>> 0693 auto spawn(const basic_yield_context<Executor>& ctx, allocator_arg_t, 0694 StackAllocator&& stack_allocator, F&& function, 0695 CompletionToken&& token = default_completion_token_t<Executor>(), 0696 constraint_t< 0697 is_executor<Executor>::value || execution::is_executor<Executor>::value 0698 > = 0) 0699 -> decltype( 0700 async_initiate<CompletionToken, 0701 typename detail::spawn_signature< 0702 result_of_t<F(basic_yield_context<Executor>)>>::type>( 0703 declval<detail::initiate_spawn<Executor>>(), 0704 token, allocator_arg_t(), 0705 static_cast<StackAllocator&&>(stack_allocator), 0706 static_cast<F&&>(function))); 0707 0708 #endif // defined(BOOST_ASIO_HAS_BOOST_CONTEXT_FIBER) 0709 // || defined(GENERATING_DOCUMENTATION) 0710 0711 #if defined(BOOST_ASIO_HAS_BOOST_COROUTINE) \ 0712 || defined(GENERATING_DOCUMENTATION) 0713 0714 /// (Deprecated: Use overloads with a completion token.) Start a new stackful 0715 /// coroutine, calling the specified handler when it completes. 0716 /** 0717 * This function is used to launch a new coroutine. 0718 * 0719 * @param function The coroutine function. The function must have the signature: 0720 * @code void function(basic_yield_context<Executor> yield); @endcode 0721 * where Executor is the associated executor type of @c Function. 0722 * 0723 * @param attributes Boost.Coroutine attributes used to customise the coroutine. 0724 */ 0725 template <typename Function> 0726 void spawn(Function&& function, 0727 const boost::coroutines::attributes& attributes 0728 = boost::coroutines::attributes()); 0729 0730 /// (Deprecated: Use overloads with a completion token.) Start a new stackful 0731 /// coroutine, calling the specified handler when it completes. 0732 /** 0733 * This function is used to launch a new coroutine. 0734 * 0735 * @param handler A handler to be called when the coroutine exits. More 0736 * importantly, the handler provides an execution context (via the the handler 0737 * invocation hook) for the coroutine. The handler must have the signature: 0738 * @code void handler(); @endcode 0739 * 0740 * @param function The coroutine function. The function must have the signature: 0741 * @code void function(basic_yield_context<Executor> yield); @endcode 0742 * where Executor is the associated executor type of @c Handler. 0743 * 0744 * @param attributes Boost.Coroutine attributes used to customise the coroutine. 0745 */ 0746 template <typename Handler, typename Function> 0747 void spawn(Handler&& handler, Function&& function, 0748 const boost::coroutines::attributes& attributes 0749 = boost::coroutines::attributes(), 0750 constraint_t< 0751 !is_executor<decay_t<Handler>>::value && 0752 !execution::is_executor<decay_t<Handler>>::value && 0753 !is_convertible<Handler&, execution_context&>::value 0754 > = 0); 0755 0756 /// (Deprecated: Use overloads with a completion token.) Start a new stackful 0757 /// coroutine, inheriting the execution context of another. 0758 /** 0759 * This function is used to launch a new coroutine. 0760 * 0761 * @param ctx Identifies the current coroutine as a parent of the new 0762 * coroutine. This specifies that the new coroutine should inherit the 0763 * execution context of the parent. For example, if the parent coroutine is 0764 * executing in a particular strand, then the new coroutine will execute in the 0765 * same strand. 0766 * 0767 * @param function The coroutine function. The function must have the signature: 0768 * @code void function(basic_yield_context<Executor> yield); @endcode 0769 * 0770 * @param attributes Boost.Coroutine attributes used to customise the coroutine. 0771 */ 0772 template <typename Executor, typename Function> 0773 void spawn(basic_yield_context<Executor> ctx, Function&& function, 0774 const boost::coroutines::attributes& attributes 0775 = boost::coroutines::attributes()); 0776 0777 /// (Deprecated: Use overloads with a completion token.) Start a new stackful 0778 /// coroutine that executes on a given executor. 0779 /** 0780 * This function is used to launch a new coroutine. 0781 * 0782 * @param ex Identifies the executor that will run the coroutine. The new 0783 * coroutine is automatically given its own explicit strand within this 0784 * executor. 0785 * 0786 * @param function The coroutine function. The function must have the signature: 0787 * @code void function(yield_context yield); @endcode 0788 * 0789 * @param attributes Boost.Coroutine attributes used to customise the coroutine. 0790 */ 0791 template <typename Function, typename Executor> 0792 void spawn(const Executor& ex, Function&& function, 0793 const boost::coroutines::attributes& attributes 0794 = boost::coroutines::attributes(), 0795 constraint_t< 0796 is_executor<Executor>::value || execution::is_executor<Executor>::value 0797 > = 0); 0798 0799 /// (Deprecated: Use overloads with a completion token.) Start a new stackful 0800 /// coroutine that executes on a given strand. 0801 /** 0802 * This function is used to launch a new coroutine. 0803 * 0804 * @param ex Identifies the strand that will run the coroutine. 0805 * 0806 * @param function The coroutine function. The function must have the signature: 0807 * @code void function(yield_context yield); @endcode 0808 * 0809 * @param attributes Boost.Coroutine attributes used to customise the coroutine. 0810 */ 0811 template <typename Function, typename Executor> 0812 void spawn(const strand<Executor>& ex, Function&& function, 0813 const boost::coroutines::attributes& attributes 0814 = boost::coroutines::attributes()); 0815 0816 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS) 0817 0818 /// (Deprecated: Use overloads with a completion token.) Start a new stackful 0819 /// coroutine that executes in the context of a strand. 0820 /** 0821 * This function is used to launch a new coroutine. 0822 * 0823 * @param s Identifies a strand. By starting multiple coroutines on the same 0824 * strand, the implementation ensures that none of those coroutines can execute 0825 * simultaneously. 0826 * 0827 * @param function The coroutine function. The function must have the signature: 0828 * @code void function(yield_context yield); @endcode 0829 * 0830 * @param attributes Boost.Coroutine attributes used to customise the coroutine. 0831 */ 0832 template <typename Function> 0833 void spawn(const boost::asio::io_context::strand& s, Function&& function, 0834 const boost::coroutines::attributes& attributes 0835 = boost::coroutines::attributes()); 0836 0837 #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS) 0838 0839 /// (Deprecated: Use overloads with a completion token.) Start a new stackful 0840 /// coroutine that executes on a given execution context. 0841 /** 0842 * This function is used to launch a new coroutine. 0843 * 0844 * @param ctx Identifies the execution context that will run the coroutine. The 0845 * new coroutine is implicitly given its own strand within this execution 0846 * context. 0847 * 0848 * @param function The coroutine function. The function must have the signature: 0849 * @code void function(yield_context yield); @endcode 0850 * 0851 * @param attributes Boost.Coroutine attributes used to customise the coroutine. 0852 */ 0853 template <typename Function, typename ExecutionContext> 0854 void spawn(ExecutionContext& ctx, Function&& function, 0855 const boost::coroutines::attributes& attributes 0856 = boost::coroutines::attributes(), 0857 constraint_t< 0858 is_convertible<ExecutionContext&, execution_context&>::value 0859 > = 0); 0860 0861 #endif // defined(BOOST_ASIO_HAS_BOOST_COROUTINE) 0862 // || defined(GENERATING_DOCUMENTATION) 0863 0864 /*@}*/ 0865 0866 } // namespace asio 0867 } // namespace boost 0868 0869 #include <boost/asio/detail/pop_options.hpp> 0870 0871 #include <boost/asio/impl/spawn.hpp> 0872 0873 #endif // BOOST_ASIO_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 |
![]() ![]() |