diff --git a/include/beman/execution/detail/as_awaitable.hpp b/include/beman/execution/detail/as_awaitable.hpp index 0d96038e..e97cca55 100644 --- a/include/beman/execution/detail/as_awaitable.hpp +++ b/include/beman/execution/detail/as_awaitable.hpp @@ -9,17 +9,26 @@ import std; #else #include +#include #include #include #endif #ifdef BEMAN_HAS_MODULES import beman.execution.detail.awaitable_sender; +import beman.execution.detail.get_await_completion_adaptor; +import beman.execution.detail.get_env; +import beman.execution.detail.query_with_default; import beman.execution.detail.is_awaitable; +import beman.execution.detail.sender; import beman.execution.detail.sender_awaitable; import beman.execution.detail.unspecified_promise; #else #include +#include +#include +#include #include +#include #include #include #endif @@ -40,12 +49,25 @@ struct as_awaitable_t { Promise>, "as_awaitable must return an awaitable"); return ::std::forward(expr).as_awaitable(promise); - } else if constexpr (::beman::execution::detail:: - is_awaitable || - !::beman::execution::detail::awaitable_sender) { - return ::std::forward(expr); + } else if constexpr (::beman::execution::sender && + !::beman::execution::detail:: + is_awaitable) { + auto adaptor = + ::beman::execution::detail::query_with_default(::beman::execution::get_await_completion_adaptor, + ::beman::execution::get_env(expr), + ::std::identity{}); + using sender_t = ::std::invoke_result_t; + if constexpr (::beman::execution::detail::awaitable_sender) { + return ::beman::execution::detail::sender_awaitable{ + adaptor(::std::forward(expr)), promise}; + } else if constexpr (::beman::execution::detail::awaitable_sender) { + return ::beman::execution::detail::sender_awaitable{::std::forward(expr), + promise}; + } else { + return ::std::forward(expr); + } } else { - return ::beman::execution::detail::sender_awaitable{::std::forward(expr), promise}; + return ::std::forward(expr); } } }; diff --git a/include/beman/execution/detail/get_await_completion_adaptor.hpp b/include/beman/execution/detail/get_await_completion_adaptor.hpp new file mode 100644 index 00000000..d0a7cf5e --- /dev/null +++ b/include/beman/execution/detail/get_await_completion_adaptor.hpp @@ -0,0 +1,38 @@ +// include/beman/execution/detail/get_await_completion_adaptor.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION_DETAIL_GET_AWAIT_COMPLETION_ADAPTOR +#define INCLUDED_BEMAN_EXECUTION_DETAIL_GET_AWAIT_COMPLETION_ADAPTOR + +#include +#ifdef BEMAN_HAS_IMPORT_STD +import std; +#else +#include +#endif +#ifdef BEMAN_HAS_MODULES +import beman.execution.detail.forwarding_query; +#else +#include +#endif + +// ---------------------------------------------------------------------------- + +namespace beman::execution { +struct get_await_completion_adaptor_t { + template + requires requires(Env&& env, const get_await_completion_adaptor_t& g) { + { ::std::as_const(env).query(g) } noexcept; + } + auto operator()(Env&& env) const noexcept { + return ::std::as_const(env).query(*this); + } + static constexpr auto query(const ::beman::execution::forwarding_query_t&) noexcept -> bool { return true; } +}; + +inline constexpr get_await_completion_adaptor_t get_await_completion_adaptor{}; +} // namespace beman::execution + +// ---------------------------------------------------------------------------- + +#endif // INCLUDED_BEMAN_EXECUTION_DETAIL_GET_AWAIT_COMPLETION_ADAPTOR diff --git a/include/beman/execution/detail/has_completions.hpp b/include/beman/execution/detail/has_completions.hpp index ae660fbc..ec229006 100644 --- a/include/beman/execution/detail/has_completions.hpp +++ b/include/beman/execution/detail/has_completions.hpp @@ -16,11 +16,13 @@ import beman.execution.detail.valid_completion_for; // ---------------------------------------------------------------------------- namespace beman::execution::detail { + +template ... Signatures> +auto has_completions_test(::beman::execution::completion_signatures*) noexcept -> void {} + template -concept has_completions = requires(Completions* completions) { - []<::beman::execution::detail::valid_completion_for... Signatures>( - ::beman::execution::completion_signatures*) {}(completions); -}; +concept has_completions = + requires(Completions* completions) { ::beman::execution::detail::has_completions_test(completions); }; } // namespace beman::execution::detail // ---------------------------------------------------------------------------- diff --git a/src/beman/execution/CMakeLists.txt b/src/beman/execution/CMakeLists.txt index 24db0b21..2d24b09e 100644 --- a/src/beman/execution/CMakeLists.txt +++ b/src/beman/execution/CMakeLists.txt @@ -79,6 +79,7 @@ target_sources( ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/fwd_env.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/gather_signatures.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_allocator.hpp + ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_await_completion_adaptor.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_awaiter.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_completion_scheduler.hpp ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/get_completion_signatures.hpp @@ -259,6 +260,7 @@ if(BEMAN_USE_MODULES) fwd_env.cppm gather_signatures.cppm get_allocator.cppm + get_await_completion_adaptor.cppm get_awaiter.cppm get_completion_scheduler.cppm get_completion_signatures.cppm diff --git a/src/beman/execution/get_await_completion_adaptor.cppm b/src/beman/execution/get_await_completion_adaptor.cppm new file mode 100644 index 00000000..0c9249e1 --- /dev/null +++ b/src/beman/execution/get_await_completion_adaptor.cppm @@ -0,0 +1,12 @@ +module; +// src/beman/execution/get_await_completion_adaptor.cppm -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +export module beman.execution.detail.get_await_completion_adaptor; + +namespace beman::execution { +export using beman::execution::get_await_completion_adaptor_t; +export using beman::execution::get_await_completion_adaptor; +} // namespace beman::execution