Skip to content

Commit b8d3972

Browse files
authored
Implement sync_wait_with_variant (#243)
1 parent 11418df commit b8d3972

File tree

7 files changed

+181
-2
lines changed

7 files changed

+181
-2
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// include/beman/execution/detail/sync_wait_with_variant.hpp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#ifndef INCLUDED_BEMAN_EXECUTION_DETAIL_SYNC_WAIT_WITH_VARIANT
5+
#define INCLUDED_BEMAN_EXECUTION_DETAIL_SYNC_WAIT_WITH_VARIANT
6+
7+
#include <beman/execution/detail/common.hpp>
8+
#include <beman/execution/detail/suppress_push.hpp>
9+
#ifdef BEMAN_HAS_IMPORT_STD
10+
import std;
11+
#else
12+
#include <optional>
13+
#include <utility>
14+
#endif
15+
#ifdef BEMAN_HAS_MODULES
16+
import beman.execution.detail.apply_sender;
17+
import beman.execution.detail.callable;
18+
import beman.execution.detail.call_result_t;
19+
import beman.execution.detail.get_domain_early;
20+
import beman.execution.detail.into_variant;
21+
import beman.execution.detail.sender_in;
22+
import beman.execution.detail.sync_wait;
23+
import beman.execution.detail.value_types_of_t;
24+
#else
25+
#include <beman/execution/detail/apply_sender.hpp>
26+
#include <beman/execution/detail/callable.hpp>
27+
#include <beman/execution/detail/call_result_t.hpp>
28+
#include <beman/execution/detail/get_domain_early.hpp>
29+
#include <beman/execution/detail/into_variant.hpp>
30+
#include <beman/execution/detail/sender_in.hpp>
31+
#include <beman/execution/detail/sync_wait.hpp>
32+
#include <beman/execution/detail/value_types_of_t.hpp>
33+
#endif
34+
35+
// ----------------------------------------------------------------------------
36+
37+
namespace beman::execution::detail {
38+
template <::beman::execution::sender_in<::beman::execution::detail::sync_wait_env> Sndr>
39+
using sync_wait_with_variant_result_type =
40+
::std::optional<::beman::execution::value_types_of_t<Sndr, ::beman::execution::detail::sync_wait_env>>;
41+
} // namespace beman::execution::detail
42+
43+
namespace beman::execution {
44+
45+
struct sync_wait_with_variant_t {
46+
template <typename Sndr>
47+
requires ::beman::execution::detail::callable<
48+
::beman::execution::sync_wait_t,
49+
::beman::execution::detail::call_result_t<::beman::execution::into_variant_t, Sndr>>
50+
auto apply_sender(Sndr&& sndr) const {
51+
using result_type = ::beman::execution::detail::sync_wait_with_variant_result_type<Sndr>;
52+
if (auto opt_value =
53+
::beman::execution::sync_wait(::beman::execution::into_variant(::std::forward<Sndr>(sndr)))) {
54+
return result_type(::std::move(::std::get<0>(*opt_value)));
55+
}
56+
return result_type(::std::nullopt);
57+
}
58+
59+
template <typename Sndr>
60+
requires requires { typename ::beman::execution::detail::sync_wait_with_variant_result_type<Sndr>; }
61+
auto operator()(Sndr&& sndr) const {
62+
return ::beman::execution::apply_sender(
63+
::beman::execution::detail::get_domain_early(sndr), *this, ::std::forward<Sndr>(sndr));
64+
}
65+
};
66+
67+
inline constexpr sync_wait_with_variant_t sync_wait_with_variant{};
68+
} // namespace beman::execution
69+
70+
// ----------------------------------------------------------------------------
71+
72+
#include <beman/execution/detail/suppress_pop.hpp>
73+
74+
#endif // INCLUDED_BEMAN_EXECUTION_DETAIL_SYNC_WAIT_WITH_VARIANT

include/beman/execution/execution.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ import beman.execution.detail.counting_scope;
2020
import beman.execution.detail.env;
2121
import beman.execution.detail.forwarding_query;
2222
import beman.execution.detail.get_allocator;
23+
import beman.execution.detail.get_await_completion_adaptor;
2324
import beman.execution.detail.get_completion_scheduler;
2425
import beman.execution.detail.get_completion_signatures;
2526
import beman.execution.detail.get_delegation_scheduler;
2627
import beman.execution.detail.get_domain;
28+
import beman.execution.detail.get_forward_progress_guarantee;
2729
import beman.execution.detail.get_env;
2830
import beman.execution.detail.get_scheduler;
2931
import beman.execution.detail.get_stop_token;
@@ -52,7 +54,10 @@ import beman.execution.detail.spawn;
5254
//-dk:TODO? import beman.execution.detail.split;
5355
import beman.execution.detail.start;
5456
import beman.execution.detail.starts_on;
57+
import beman.execution.detail.stopped_as_error;
58+
import beman.execution.detail.stopped_as_optional;
5559
import beman.execution.detail.sync_wait;
60+
import beman.execution.detail.sync_wait_with_variant;
5661
import beman.execution.detail.then;
5762
import beman.execution.detail.valid_completion_for;
5863
import beman.execution.detail.valid_completion_signatures;
@@ -73,10 +78,12 @@ import beman.execution.detail.write_env;
7378
#include <beman/execution/detail/env.hpp>
7479
#include <beman/execution/detail/forwarding_query.hpp>
7580
#include <beman/execution/detail/get_allocator.hpp>
81+
#include <beman/execution/detail/get_await_completion_adaptor.hpp>
7682
#include <beman/execution/detail/get_completion_scheduler.hpp>
7783
#include <beman/execution/detail/get_completion_signatures.hpp>
7884
#include <beman/execution/detail/get_delegation_scheduler.hpp>
7985
#include <beman/execution/detail/get_domain.hpp>
86+
#include <beman/execution/detail/get_forward_progress_guarantee.hpp>
8087
#include <beman/execution/detail/get_env.hpp>
8188
#include <beman/execution/detail/get_scheduler.hpp>
8289
#include <beman/execution/detail/get_stop_token.hpp>
@@ -105,7 +112,10 @@ import beman.execution.detail.write_env;
105112
//-dk:TODO? #include <beman/execution/detail/split.hpp>
106113
#include <beman/execution/detail/start.hpp>
107114
#include <beman/execution/detail/starts_on.hpp>
115+
#include <beman/execution/detail/stopped_as_error.hpp>
116+
#include <beman/execution/detail/stopped_as_optional.hpp>
108117
#include <beman/execution/detail/sync_wait.hpp>
118+
#include <beman/execution/detail/sync_wait_with_variant.hpp>
109119
#include <beman/execution/detail/then.hpp>
110120
#include <beman/execution/detail/valid_completion_for.hpp>
111121
#include <beman/execution/detail/valid_completion_signatures.hpp>

src/beman/execution/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ target_sources(
182182
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/suppress_push.hpp
183183
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/suspend_complete.hpp
184184
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sync_wait.hpp
185+
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/sync_wait_with_variant.hpp
185186
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/tag_of_t.hpp
186187
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/then.hpp
187188
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/transform_sender.hpp
@@ -369,6 +370,7 @@ if(BEMAN_USE_MODULES)
369370
stopped_as_optional.cppm
370371
suspend_complete.cppm
371372
sync_wait.cppm
373+
sync_wait_with_variant.cppm
372374
tag_of_t.cppm
373375
then.cppm
374376
transform_sender.cppm

src/beman/execution/execution.cppm

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ import beman.execution.detail.stoppable_source;
6969
import beman.execution.detail.stopped_as_error;
7070
import beman.execution.detail.stopped_as_optional;
7171
import beman.execution.detail.sync_wait;
72+
import beman.execution.detail.sync_wait_with_variant;
7273
export import beman.execution.detail.tag_of_t; // [exec.getcomplsigs], completion signatures
7374
import beman.execution.detail.then;
7475
import beman.execution.detail.transform_sender;
@@ -232,10 +233,10 @@ export using ::beman::execution::run_loop;
232233

233234
// [exec.consumers], consumers
234235
export using ::beman::execution::sync_wait_t;
235-
//-dk:TODO export using ::beman::execution::sync_wait_with_variant_t;
236+
export using ::beman::execution::sync_wait_with_variant_t;
236237

237238
export using ::beman::execution::sync_wait;
238-
//-dk:TODO export using ::beman::execution::sync_wait_with_variant;
239+
export using ::beman::execution::sync_wait_with_variant;
239240

240241
// [exec.as.awaitable]
241242
export using ::beman::execution::as_awaitable_t;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module;
2+
// src/beman/execution/sync_wait_with_variant.cppm -*-C++-*-
3+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4+
5+
#include <beman/execution/detail/sync_wait_with_variant.hpp>
6+
7+
export module beman.execution.detail.sync_wait_with_variant;
8+
9+
namespace beman::execution {
10+
export using beman::execution::sync_wait_with_variant_t;
11+
export using beman::execution::sync_wait_with_variant;
12+
} // namespace beman::execution

tests/beman/execution/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ list(
6161
exec-stopped-as-error.test
6262
exec-stopped-as-optional.test
6363
exec-sync-wait.test
64+
exec-sync-wait-with-variant.test
6465
exec-then.test
6566
exec-utils-cmplsigs.test
6667
exec-when-all.test
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// src/beman/execution/tests/exec-sync-wait-with-variant.test.cpp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#include <exception>
5+
#include <concepts>
6+
#include <utility>
7+
#include <string>
8+
#include <tuple>
9+
#include <variant>
10+
#include <test/execution.hpp>
11+
#ifdef BEMAN_HAS_MODULES
12+
import beman.execution;
13+
import beman.execution.detail;
14+
#else
15+
#include <beman/execution/execution.hpp>
16+
#endif
17+
18+
// ----------------------------------------------------------------------------
19+
20+
namespace {
21+
22+
template <typename... Values>
23+
struct just_variant {
24+
using sender_concept = test_std::sender_t;
25+
using completion_signatures = test_std::completion_signatures<test_std::set_value_t(Values)...>;
26+
27+
template <typename, typename...>
28+
static consteval auto get_completion_signatures() -> completion_signatures {
29+
return {};
30+
}
31+
32+
template <typename Receiver>
33+
struct state {
34+
using operation_state_concept = test_std::operation_state_t;
35+
36+
auto start() & noexcept -> void {
37+
std::visit([this](auto v) { test_std::set_value(std::move(receiver), std::move(v)); }, std::move(var));
38+
}
39+
40+
std::variant<Values...> var;
41+
Receiver receiver;
42+
};
43+
44+
template <typename Receiver>
45+
auto connect(Receiver receiver) && noexcept -> state<Receiver> {
46+
return {std::move(var), ::std::move(receiver)};
47+
}
48+
49+
std::variant<Values...> var;
50+
};
51+
52+
auto test_sync_wait_with_variant_multi_value() -> void {
53+
auto result1 = test_std::sync_wait_with_variant(just_variant<int, float>{114});
54+
static_assert(std::same_as<decltype(result1), std::optional<std::variant<std::tuple<int>, std::tuple<float>>>>);
55+
ASSERT(result1.has_value());
56+
ASSERT(result1.value().index() == 0);
57+
ASSERT(std::get<0>(*result1) == std::tuple{114});
58+
59+
auto result2 = test_std::sync_wait_with_variant(just_variant<int, std::string>{"hello"});
60+
static_assert(
61+
std::same_as<decltype(result2), std::optional<std::variant<std::tuple<int>, std::tuple<std::string>>>>);
62+
ASSERT(result2.has_value());
63+
ASSERT(result2.value().index() == 1);
64+
ASSERT(std::get<1>(*result2) == std::tuple<std::string>{"hello"});
65+
}
66+
67+
auto test_sync_wait_with_variant_single_value() -> void {
68+
auto value = test_std::sync_wait_with_variant(test_std::just(514));
69+
static_assert(std::same_as<decltype(value), std::optional<std::variant<std::tuple<int>>>>);
70+
ASSERT(value.has_value());
71+
ASSERT(std::get<0>(*value) == std::tuple{514});
72+
}
73+
74+
} // namespace
75+
76+
TEST(exec_sync_wait_with_variant) {
77+
test_sync_wait_with_variant_multi_value();
78+
test_sync_wait_with_variant_single_value();
79+
}

0 commit comments

Comments
 (0)