Skip to content

Commit 0587b8f

Browse files
committed
WIP: initial implementation of D3206R0
1 parent ad1bb84 commit 0587b8f

File tree

8 files changed

+174
-10
lines changed

8 files changed

+174
-10
lines changed

include/beman/execution26/detail/basic_sender.hpp

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,29 @@ struct basic_sender : ::beman::execution26::detail::product_type<Tag, Data, Chil
3939
data.children);
4040
}
4141

42+
template <class Self, class Env>
43+
constexpr auto get_completion_behaviour(this Self&& self, Env&& env) noexcept -> decltype(auto) {
44+
auto data{::beman::execution26::detail::get_sender_data(self)};
45+
return ::std::apply(
46+
[&data, &env](auto&&... cs) {
47+
return ::beman::execution26::detail::impls_for<Tag>::get_completion_behaviour(
48+
::std::forward<Env>(env),
49+
::beman::execution26::detail::forward_like<Self>(data.data),
50+
::beman::execution26::detail::forward_like<Self>(cs)...);
51+
},
52+
::beman::execution26::detail::forward_like<Self>(data.children));
53+
}
54+
4255
template <typename Receiver>
43-
requires(not::beman::execution26::receiver<Receiver>)
56+
requires(not ::beman::execution26::receiver<Receiver>)
4457
auto connect(Receiver receiver) = BEMAN_EXECUTION26_DELETE("the passed receiver doesn't model receiver");
4558

4659
private:
4760
#if __cpp_explicit_this_parameter < 302110L //-dk:TODO need to figure out how to use explicit this with forwarding
4861
template <::beman::execution26::receiver Receiver>
4962
auto connect(Receiver receiver) & noexcept(
50-
noexcept(::beman::execution26::detail::basic_operation<basic_sender&, Receiver>{*this, ::std::move(receiver)}))
51-
-> ::beman::execution26::detail::basic_operation<basic_sender&, Receiver> {
63+
noexcept(::beman::execution26::detail::basic_operation<basic_sender&, Receiver>{
64+
*this, ::std::move(receiver)})) -> ::beman::execution26::detail::basic_operation<basic_sender&, Receiver> {
5265
return {*this, ::std::move(receiver)};
5366
}
5467
template <::beman::execution26::receiver Receiver>
@@ -59,18 +72,18 @@ struct basic_sender : ::beman::execution26::detail::product_type<Tag, Data, Chil
5972
}
6073
template <::beman::execution26::receiver Receiver>
6174
auto connect(Receiver receiver) && noexcept(
62-
noexcept(::beman::execution26::detail::basic_operation<basic_sender, Receiver>{::std::move(*this),
63-
::std::move(receiver)}))
64-
-> ::beman::execution26::detail::basic_operation<basic_sender, Receiver> {
75+
noexcept(::beman::execution26::detail::basic_operation<basic_sender, Receiver>{
76+
::std::move(*this),
77+
::std::move(receiver)})) -> ::beman::execution26::detail::basic_operation<basic_sender, Receiver> {
6578
return {::std::move(*this), ::std::move(receiver)};
6679
}
6780
#else
6881
template <::beman::execution26::detail::decays_to<basic_sender> Self, ::beman::execution26::receiver Receiver>
6982
auto
7083
connect(this Self&& self,
7184
Receiver receiver) noexcept(noexcept(::beman::execution26::detail::basic_operation<basic_sender, Receiver>{
72-
::std::forward<Self>(self), ::std::move(receiver)}))
73-
-> ::beman::execution26::detail::basic_operation<Self, Receiver> {
85+
::std::forward<Self>(self),
86+
::std::move(receiver)})) -> ::beman::execution26::detail::basic_operation<Self, Receiver> {
7487
return {::std::forward<Self>(self), ::std::move(receiver)};
7588
}
7689
#endif
@@ -101,6 +114,12 @@ struct basic_sender : ::beman::execution26::detail::product_type<Tag, Data, Chil
101114
-> ::beman::execution26::detail::completion_signatures_for<Self, Env> {
102115
return {};
103116
}
117+
118+
template <::beman::execution26::detail::decays_to<basic_sender> Self, typename Env>
119+
auto get_completion_behaviour(this Self&&, Env&&) noexcept
120+
-> ::beman::execution26::detail::completion_signatures_for<Self, Env> {
121+
return {};
122+
}
104123
#endif
105124
};
106125
} // namespace beman::execution26::detail
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// include/beman/execution26/detail/completion_behaviour.hpp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_COMPLETION_BEHAVIOUR
5+
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_COMPLETION_BEHAVIOUR
6+
7+
#include <cstdint>
8+
9+
namespace beman::execution26 {
10+
enum class completion_behaviour : std::uint8_t { inline_completion, synchronous, asynchronous, unknown };
11+
} // namespace beman::execution26
12+
13+
#endif

include/beman/execution26/detail/default_impls.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ struct default_impls {
5252
static_assert(Index::value == 0);
5353
Tag()(::std::move(receiver), ::std::forward<Args>(args)...);
5454
};
55+
static constexpr auto get_completion_behaviour =
56+
[](const auto& /* env */, const auto& /* data */, const auto&... /* children */) noexcept {
57+
return ::beman::execution26::completion_behaviour::unknown;
58+
};
5559
};
5660
} // namespace beman::execution26::detail
5761

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// include/beman/execution26/detail/get_completion_behaviour.hpp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_COMPLETION_BEHAVIOUR
5+
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_COMPLETION_BEHAVIOUR
6+
7+
#include <beman/execution26/detail/completion_behaviour.hpp>
8+
#include <beman/execution26/detail/forward_like.hpp>
9+
#include <beman/execution26/detail/is_awaitable.hpp>
10+
#include <beman/execution26/detail/get_domain_late.hpp>
11+
#include <beman/execution26/detail/transform_sender.hpp>
12+
13+
#include <type_traits>
14+
15+
namespace beman::execution26 {
16+
17+
struct get_completion_behaviour_t {
18+
template <class Sender>
19+
constexpr auto operator()(Sender&& sender) const noexcept {
20+
if constexpr (requires { typename ::std::remove_cvref_t<Sender>::completion_behaviour; }) {
21+
return typename ::std::remove_cvref_t<Sender>::completion_behaviour{};
22+
} else if constexpr (requires { ::std::forward<Sender>(sender).get_completion_behaviour(); }) {
23+
return ::std::forward<Sender>(sender).get_completion_behaviour();
24+
} else if constexpr (::beman::execution26::detail::is_awaitable<
25+
::std::remove_cvref_t<Sender>,
26+
::beman::execution26::detail::env_promise<::beman::execution26::empty_env>>) {
27+
return sender.await_ready() ? ::beman::execution26::completion_behaviour::inline_completion
28+
: ::beman::execution26::completion_behaviour::unknown;
29+
} else {
30+
return ::beman::execution26::completion_behaviour::unknown;
31+
}
32+
}
33+
34+
template <class Sender, class Env>
35+
constexpr auto operator()(Sender&& sender, Env&& env) const noexcept {
36+
auto new_sender{[](auto&& sndr, auto&& e) -> decltype(auto) {
37+
auto domain{::beman::execution26::detail::get_domain_late(sndr, e)};
38+
return ::beman::execution26::transform_sender(
39+
domain, ::std::forward<Sender>(sndr), ::std::forward<Env>(e));
40+
}};
41+
42+
using new_sender_type =
43+
::std::remove_cvref_t<decltype(new_sender(::std::forward<Sender>(sender), ::std::forward<Env>(env)))>;
44+
using decayed_env = ::std::remove_cvref_t<Env>;
45+
46+
if constexpr (requires { typename new_sender_type::completion_behaviour; }) {
47+
return typename new_sender_type::completion_behaviour{};
48+
} else if constexpr (requires { ::std::move(new_sender).get_completion_behaviour(std::forward<Env>(env)); }) {
49+
return std::move(new_sender).get_completion_behaviour(std::forward<Env>(env));
50+
} else if constexpr (::beman::execution26::detail::is_awaitable<
51+
new_sender_type,
52+
::beman::execution26::detail::env_promise<decayed_env>>) {
53+
if (new_sender(sender, env).await_ready()) {
54+
return completion_behaviour::inline_completion;
55+
} else {
56+
return completion_behaviour::unknown;
57+
}
58+
} else {
59+
return completion_behaviour::unknown;
60+
}
61+
}
62+
};
63+
64+
inline constexpr get_completion_behaviour_t get_completion_behaviour{};
65+
66+
} // namespace beman::execution26
67+
68+
#endif

include/beman/execution26/detail/just.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222

2323
namespace beman::execution26::detail {
2424
template <typename Completion, typename... T>
25-
concept just_size = (not::std::same_as<Completion, ::beman::execution26::set_error_t> or 1u == sizeof...(T)) &&
26-
(not::std::same_as<Completion, ::beman::execution26::set_stopped_t> or 0u == sizeof...(T));
25+
concept just_size = (not ::std::same_as<Completion, ::beman::execution26::set_error_t> or 1u == sizeof...(T)) &&
26+
(not ::std::same_as<Completion, ::beman::execution26::set_stopped_t> or 0u == sizeof...(T));
2727
template <typename Completion>
2828
struct just_t {
2929
template <typename... T>
@@ -49,6 +49,10 @@ struct impls_for<just_t<Completion>> : ::beman::execution26::detail::default_imp
4949
Completion()(::std::move(receiver), ::std::move(state.template get<I>())...);
5050
}(::std::make_index_sequence<State::size()>{});
5151
};
52+
53+
static constexpr auto get_completion_behaviour = [](const auto&, const auto&, const auto&) {
54+
return ::beman::execution26::completion_behaviour::inline_completion;
55+
};
5256
};
5357
} // namespace beman::execution26::detail
5458

src/beman/execution26/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ target_sources(
5353
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/child_type.hpp
5454
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/class_type.hpp
5555
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/common.hpp
56+
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/completion_behaviour.hpp
5657
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/completion_domain.hpp
5758
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/completion_signature.hpp
5859
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/completion_signatures.hpp
@@ -84,6 +85,7 @@ target_sources(
8485
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/gather_signatures.hpp
8586
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/get_allocator.hpp
8687
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/get_awaiter.hpp
88+
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/get_completion_behaviour.hpp
8789
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/get_completion_scheduler.hpp
8890
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/get_completion_signatures.hpp
8991
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/get_delegation_scheduler.hpp

tests/beman/execution26/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ list(
2323
exec-general.test
2424
exec-get-allocator.test
2525
exec-get-compl-sched.test
26+
exec-get-completion-behaviour.test
2627
exec-get-delegation-scheduler.test
2728
exec-get-domain.test
2829
exec-get-env.test
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// src/beman/execution26/tests/exec-get-completion-behaviour.test.cpp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#include <beman/execution26/detail/get_completion_behaviour.hpp>
5+
6+
#include <test/execution.hpp>
7+
8+
#include <type_traits>
9+
10+
namespace {
11+
12+
template <auto Value>
13+
using value = std::integral_constant<decltype(Value), Value>;
14+
15+
struct awaitable {
16+
static constexpr auto await_ready() noexcept -> bool { return true; }
17+
auto await_suspend(auto parent) noexcept { return parent; }
18+
auto await_resume() noexcept -> void {}
19+
};
20+
21+
void test_constexpr_awaitable() {
22+
auto completion_behaviour = value<test_std::get_completion_behaviour(awaitable{})>{};
23+
ASSERT(test_std::completion_behaviour::inline_completion == completion_behaviour);
24+
}
25+
struct sender {
26+
using completion_behaviour = value<test_std::completion_behaviour::inline_completion>;
27+
};
28+
29+
struct sender2 {
30+
static constexpr auto get_completion_behaviour() noexcept -> test_std::completion_behaviour {
31+
return test_std::completion_behaviour::inline_completion;
32+
}
33+
};
34+
35+
void test_typedef_sender() {
36+
auto completion_behaviour =
37+
std::integral_constant<test_std::completion_behaviour, test_std::get_completion_behaviour(sender{})>{};
38+
ASSERT(test_std::completion_behaviour::inline_completion == completion_behaviour);
39+
}
40+
41+
void test_constexpr_sender() {
42+
auto completion_behaviour =
43+
std::integral_constant<test_std::completion_behaviour, test_std::get_completion_behaviour(sender{})>{};
44+
ASSERT(test_std::completion_behaviour::inline_completion == completion_behaviour);
45+
}
46+
47+
} // namespace
48+
49+
TEST(exec_get_completion_behaviour) {
50+
test_constexpr_awaitable();
51+
test_typedef_sender();
52+
test_constexpr_sender();
53+
}

0 commit comments

Comments
 (0)