Add standard executor support to co_spawn.

This commit is contained in:
Christopher Kohlhoff 2020-06-19 23:04:25 +10:00
parent 01c20f6365
commit 4658609599
2 changed files with 58 additions and 10 deletions

View File

@ -20,6 +20,7 @@
#if defined(ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION) #if defined(ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION)
#include "asio/awaitable.hpp" #include "asio/awaitable.hpp"
#include "asio/execution/executor.hpp"
#include "asio/execution_context.hpp" #include "asio/execution_context.hpp"
#include "asio/is_executor.hpp" #include "asio/is_executor.hpp"
@ -105,7 +106,7 @@ co_spawn(const Executor& ex, awaitable<T, AwaitableExecutor> a,
CompletionToken&& token CompletionToken&& token
ASIO_DEFAULT_COMPLETION_TOKEN(Executor), ASIO_DEFAULT_COMPLETION_TOKEN(Executor),
typename enable_if< typename enable_if<
is_executor<Executor>::value (is_executor<Executor>::value || execution::is_executor<Executor>::value)
&& is_convertible<Executor, AwaitableExecutor>::value && is_convertible<Executor, AwaitableExecutor>::value
>::type* = 0); >::type* = 0);
@ -161,7 +162,7 @@ co_spawn(const Executor& ex, awaitable<void, AwaitableExecutor> a,
CompletionToken&& token CompletionToken&& token
ASIO_DEFAULT_COMPLETION_TOKEN(Executor), ASIO_DEFAULT_COMPLETION_TOKEN(Executor),
typename enable_if< typename enable_if<
is_executor<Executor>::value (is_executor<Executor>::value || execution::is_executor<Executor>::value)
&& is_convertible<Executor, AwaitableExecutor>::value && is_convertible<Executor, AwaitableExecutor>::value
>::type* = 0); >::type* = 0);
@ -371,7 +372,7 @@ co_spawn(const Executor& ex, F&& f,
CompletionToken&& token CompletionToken&& token
ASIO_DEFAULT_COMPLETION_TOKEN(Executor), ASIO_DEFAULT_COMPLETION_TOKEN(Executor),
typename enable_if< typename enable_if<
is_executor<Executor>::value is_executor<Executor>::value || execution::is_executor<Executor>::value
>::type* = 0); >::type* = 0);
/// Spawn a new coroutined-based thread of execution. /// Spawn a new coroutined-based thread of execution.

View File

@ -18,7 +18,9 @@
#include "asio/detail/config.hpp" #include "asio/detail/config.hpp"
#include "asio/awaitable.hpp" #include "asio/awaitable.hpp"
#include "asio/dispatch.hpp" #include "asio/dispatch.hpp"
#include "asio/execution/outstanding_work.hpp"
#include "asio/post.hpp" #include "asio/post.hpp"
#include "asio/prefer.hpp"
#include "asio/use_awaitable.hpp" #include "asio/use_awaitable.hpp"
#include "asio/detail/push_options.hpp" #include "asio/detail/push_options.hpp"
@ -26,12 +28,56 @@
namespace asio { namespace asio {
namespace detail { namespace detail {
template <typename Executor, typename = void>
class co_spawn_work_guard
{
public:
typedef typename decay<
typename prefer_result_type<Executor,
execution::outstanding_work_t::tracked_t
>::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 <typename Executor>
struct co_spawn_work_guard<Executor,
typename enable_if<
!execution::is_executor<Executor>::value
>::type> : executor_work_guard<Executor>
{
co_spawn_work_guard(const Executor& ex)
: executor_work_guard<Executor>(ex)
{
}
};
template <typename Executor>
inline co_spawn_work_guard<Executor>
make_co_spawn_work_guard(const Executor& ex)
{
return co_spawn_work_guard<Executor>(ex);
}
template <typename T, typename Executor, typename F, typename Handler> template <typename T, typename Executor, typename F, typename Handler>
awaitable<void, Executor> co_spawn_entry_point( awaitable<void, Executor> co_spawn_entry_point(
awaitable<T, Executor>*, Executor ex, F f, Handler handler) awaitable<T, Executor>*, Executor ex, F f, Handler handler)
{ {
auto spawn_work = make_work_guard(ex); auto spawn_work = make_co_spawn_work_guard(ex);
auto handler_work = make_work_guard(handler, ex); auto handler_work = make_co_spawn_work_guard(
asio::get_associated_executor(handler, ex));
(void) co_await (post)(spawn_work.get_executor(), (void) co_await (post)(spawn_work.get_executor(),
use_awaitable_t<Executor>{}); use_awaitable_t<Executor>{});
@ -66,8 +112,9 @@ template <typename Executor, typename F, typename Handler>
awaitable<void, Executor> co_spawn_entry_point( awaitable<void, Executor> co_spawn_entry_point(
awaitable<void, Executor>*, Executor ex, F f, Handler handler) awaitable<void, Executor>*, Executor ex, F f, Handler handler)
{ {
auto spawn_work = make_work_guard(ex); auto spawn_work = make_co_spawn_work_guard(ex);
auto handler_work = make_work_guard(handler, ex); auto handler_work = make_co_spawn_work_guard(
asio::get_associated_executor(handler, ex));
(void) co_await (post)(spawn_work.get_executor(), (void) co_await (post)(spawn_work.get_executor(),
use_awaitable_t<Executor>{__FILE__, __LINE__, "co_spawn_entry_point"}); use_awaitable_t<Executor>{__FILE__, __LINE__, "co_spawn_entry_point"});
@ -148,7 +195,7 @@ inline ASIO_INITFN_AUTO_RESULT_TYPE(
co_spawn(const Executor& ex, co_spawn(const Executor& ex,
awaitable<T, AwaitableExecutor> a, CompletionToken&& token, awaitable<T, AwaitableExecutor> a, CompletionToken&& token,
typename enable_if< typename enable_if<
is_executor<Executor>::value (is_executor<Executor>::value || execution::is_executor<Executor>::value)
&& is_convertible<Executor, AwaitableExecutor>::value && is_convertible<Executor, AwaitableExecutor>::value
>::type*) >::type*)
{ {
@ -165,7 +212,7 @@ inline ASIO_INITFN_AUTO_RESULT_TYPE(
co_spawn(const Executor& ex, co_spawn(const Executor& ex,
awaitable<void, AwaitableExecutor> a, CompletionToken&& token, awaitable<void, AwaitableExecutor> a, CompletionToken&& token,
typename enable_if< typename enable_if<
is_executor<Executor>::value (is_executor<Executor>::value || execution::is_executor<Executor>::value)
&& is_convertible<Executor, AwaitableExecutor>::value && is_convertible<Executor, AwaitableExecutor>::value
>::type*) >::type*)
{ {
@ -216,7 +263,7 @@ inline ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken,
typename detail::awaitable_signature<typename result_of<F()>::type>::type) typename detail::awaitable_signature<typename result_of<F()>::type>::type)
co_spawn(const Executor& ex, F&& f, CompletionToken&& token, co_spawn(const Executor& ex, F&& f, CompletionToken&& token,
typename enable_if< typename enable_if<
is_executor<Executor>::value is_executor<Executor>::value || execution::is_executor<Executor>::value
>::type*) >::type*)
{ {
return async_initiate<CompletionToken, return async_initiate<CompletionToken,