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