// // impl/spawn.hpp // ~~~~~~~~~~~~~~ // // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_ASIO_IMPL_SPAWN_HPP #define BOOST_ASIO_IMPL_SPAWN_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace asio { namespace detail { template class coro_handler { public: coro_handler(basic_yield_context ctx) : coro_(ctx.coro_.lock()), ca_(ctx.ca_), handler_(ctx.handler_), ready_(0), ec_(ctx.ec_), value_(0) { } void operator()(T value) { *ec_ = boost::system::error_code(); *value_ = BOOST_ASIO_MOVE_CAST(T)(value); if (--*ready_ == 0) (*coro_)(); } void operator()(boost::system::error_code ec, T value) { *ec_ = ec; *value_ = BOOST_ASIO_MOVE_CAST(T)(value); if (--*ready_ == 0) (*coro_)(); } //private: shared_ptr::callee_type> coro_; typename basic_yield_context::caller_type& ca_; Handler handler_; atomic_count* ready_; boost::system::error_code* ec_; T* value_; }; template class coro_handler { public: coro_handler(basic_yield_context ctx) : coro_(ctx.coro_.lock()), ca_(ctx.ca_), handler_(ctx.handler_), ready_(0), ec_(ctx.ec_) { } void operator()() { *ec_ = boost::system::error_code(); if (--*ready_ == 0) (*coro_)(); } void operator()(boost::system::error_code ec) { *ec_ = ec; if (--*ready_ == 0) (*coro_)(); } //private: shared_ptr::callee_type> coro_; typename basic_yield_context::caller_type& ca_; Handler handler_; atomic_count* ready_; boost::system::error_code* ec_; }; template inline asio_handler_allocate_is_deprecated asio_handler_allocate(std::size_t size, coro_handler* this_handler) { #if defined(BOOST_ASIO_NO_DEPRECATED) boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_); return asio_handler_allocate_is_no_longer_used(); #else // defined(BOOST_ASIO_NO_DEPRECATED) return boost_asio_handler_alloc_helpers::allocate( size, this_handler->handler_); #endif // defined(BOOST_ASIO_NO_DEPRECATED) } template inline asio_handler_deallocate_is_deprecated asio_handler_deallocate(void* pointer, std::size_t size, coro_handler* this_handler) { boost_asio_handler_alloc_helpers::deallocate( pointer, size, this_handler->handler_); #if defined(BOOST_ASIO_NO_DEPRECATED) return asio_handler_deallocate_is_no_longer_used(); #endif // defined(BOOST_ASIO_NO_DEPRECATED) } template inline bool asio_handler_is_continuation(coro_handler*) { return true; } template inline asio_handler_invoke_is_deprecated asio_handler_invoke(Function& function, coro_handler* this_handler) { boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); #if defined(BOOST_ASIO_NO_DEPRECATED) return asio_handler_invoke_is_no_longer_used(); #endif // defined(BOOST_ASIO_NO_DEPRECATED) } template inline asio_handler_invoke_is_deprecated asio_handler_invoke(const Function& function, coro_handler* this_handler) { boost_asio_handler_invoke_helpers::invoke( function, this_handler->handler_); #if defined(BOOST_ASIO_NO_DEPRECATED) return asio_handler_invoke_is_no_longer_used(); #endif // defined(BOOST_ASIO_NO_DEPRECATED) } template class coro_async_result { public: typedef coro_handler completion_handler_type; typedef T return_type; explicit coro_async_result(completion_handler_type& h) : handler_(h), ca_(h.ca_), ready_(2) { h.ready_ = &ready_; out_ec_ = h.ec_; if (!out_ec_) h.ec_ = &ec_; h.value_ = &value_; } return_type get() { // Must not hold shared_ptr to coro while suspended. handler_.coro_.reset(); if (--ready_ != 0) ca_(); if (!out_ec_ && ec_) throw boost::system::system_error(ec_); return BOOST_ASIO_MOVE_CAST(return_type)(value_); } private: completion_handler_type& handler_; typename basic_yield_context::caller_type& ca_; atomic_count ready_; boost::system::error_code* out_ec_; boost::system::error_code ec_; return_type value_; }; template class coro_async_result { public: typedef coro_handler completion_handler_type; typedef void return_type; explicit coro_async_result(completion_handler_type& h) : handler_(h), ca_(h.ca_), ready_(2) { h.ready_ = &ready_; out_ec_ = h.ec_; if (!out_ec_) h.ec_ = &ec_; } void get() { // Must not hold shared_ptr to coro while suspended. handler_.coro_.reset(); if (--ready_ != 0) ca_(); if (!out_ec_ && ec_) throw boost::system::system_error(ec_); } private: completion_handler_type& handler_; typename basic_yield_context::caller_type& ca_; atomic_count ready_; boost::system::error_code* out_ec_; boost::system::error_code ec_; }; } // namespace detail #if !defined(GENERATING_DOCUMENTATION) template class async_result, ReturnType()> : public detail::coro_async_result { public: explicit async_result( typename detail::coro_async_result::completion_handler_type& h) : detail::coro_async_result(h) { } }; template class async_result, ReturnType(Arg1)> : public detail::coro_async_result::type> { public: explicit async_result( typename detail::coro_async_result::type>::completion_handler_type& h) : detail::coro_async_result::type>(h) { } }; template class async_result, ReturnType(boost::system::error_code)> : public detail::coro_async_result { public: explicit async_result( typename detail::coro_async_result::completion_handler_type& h) : detail::coro_async_result(h) { } }; template class async_result, ReturnType(boost::system::error_code, Arg2)> : public detail::coro_async_result::type> { public: explicit async_result( typename detail::coro_async_result::type>::completion_handler_type& h) : detail::coro_async_result::type>(h) { } }; template