diff --git a/asio/include/asio/co_spawn.hpp b/asio/include/asio/co_spawn.hpp index e18b5dff..38ee7ff4 100644 --- a/asio/include/asio/co_spawn.hpp +++ b/asio/include/asio/co_spawn.hpp @@ -20,6 +20,7 @@ #if defined(ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION) #include "asio/awaitable.hpp" +#include "asio/execution/executor.hpp" #include "asio/execution_context.hpp" #include "asio/is_executor.hpp" @@ -105,7 +106,7 @@ co_spawn(const Executor& ex, awaitable a, CompletionToken&& token ASIO_DEFAULT_COMPLETION_TOKEN(Executor), typename enable_if< - is_executor::value + (is_executor::value || execution::is_executor::value) && is_convertible::value >::type* = 0); @@ -161,7 +162,7 @@ co_spawn(const Executor& ex, awaitable a, CompletionToken&& token ASIO_DEFAULT_COMPLETION_TOKEN(Executor), typename enable_if< - is_executor::value + (is_executor::value || execution::is_executor::value) && is_convertible::value >::type* = 0); @@ -371,7 +372,7 @@ co_spawn(const Executor& ex, F&& f, CompletionToken&& token ASIO_DEFAULT_COMPLETION_TOKEN(Executor), typename enable_if< - is_executor::value + is_executor::value || execution::is_executor::value >::type* = 0); /// Spawn a new coroutined-based thread of execution. diff --git a/asio/include/asio/impl/co_spawn.hpp b/asio/include/asio/impl/co_spawn.hpp index d44a1816..c5b090a2 100644 --- a/asio/include/asio/impl/co_spawn.hpp +++ b/asio/include/asio/impl/co_spawn.hpp @@ -18,7 +18,9 @@ #include "asio/detail/config.hpp" #include "asio/awaitable.hpp" #include "asio/dispatch.hpp" +#include "asio/execution/outstanding_work.hpp" #include "asio/post.hpp" +#include "asio/prefer.hpp" #include "asio/use_awaitable.hpp" #include "asio/detail/push_options.hpp" @@ -26,12 +28,56 @@ namespace asio { namespace detail { +template +class co_spawn_work_guard +{ +public: + typedef typename decay< + typename prefer_result_type::type + >::type executor_type; + + co_spawn_work_guard(const Executor& ex) + : executor_(asio::prefer(ex, execution::outstanding_work.tracked)) + { + } + + executor_type get_executor() const ASIO_NOEXCEPT + { + return executor_; + } + +private: + executor_type executor_; +}; + +template +struct co_spawn_work_guard::value + >::type> : executor_work_guard +{ + co_spawn_work_guard(const Executor& ex) + : executor_work_guard(ex) + { + } +}; + +template +inline co_spawn_work_guard +make_co_spawn_work_guard(const Executor& ex) +{ + return co_spawn_work_guard(ex); +} + template awaitable co_spawn_entry_point( awaitable*, Executor ex, F f, Handler handler) { - auto spawn_work = make_work_guard(ex); - auto handler_work = make_work_guard(handler, ex); + auto spawn_work = make_co_spawn_work_guard(ex); + auto handler_work = make_co_spawn_work_guard( + asio::get_associated_executor(handler, ex)); (void) co_await (post)(spawn_work.get_executor(), use_awaitable_t{}); @@ -66,8 +112,9 @@ template awaitable co_spawn_entry_point( awaitable*, Executor ex, F f, Handler handler) { - auto spawn_work = make_work_guard(ex); - auto handler_work = make_work_guard(handler, ex); + auto spawn_work = make_co_spawn_work_guard(ex); + auto handler_work = make_co_spawn_work_guard( + asio::get_associated_executor(handler, ex)); (void) co_await (post)(spawn_work.get_executor(), use_awaitable_t{__FILE__, __LINE__, "co_spawn_entry_point"}); @@ -148,7 +195,7 @@ inline ASIO_INITFN_AUTO_RESULT_TYPE( co_spawn(const Executor& ex, awaitable a, CompletionToken&& token, typename enable_if< - is_executor::value + (is_executor::value || execution::is_executor::value) && is_convertible::value >::type*) { @@ -165,7 +212,7 @@ inline ASIO_INITFN_AUTO_RESULT_TYPE( co_spawn(const Executor& ex, awaitable a, CompletionToken&& token, typename enable_if< - is_executor::value + (is_executor::value || execution::is_executor::value) && is_convertible::value >::type*) { @@ -216,7 +263,7 @@ inline ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, typename detail::awaitable_signature::type>::type) co_spawn(const Executor& ex, F&& f, CompletionToken&& token, typename enable_if< - is_executor::value + is_executor::value || execution::is_executor::value >::type*) { return async_initiate