kokkos-execution 0.0.1
Loading...
Searching...
No Matches
test_then.cpp
Go to the documentation of this file.
3
10
22
24
25using namespace Kokkos::utils::callbacks;
26
40
42consteval bool test_sndr_traits() {
44 using schd_sndr_t = typename ThenTest::schedule_sender_t;
45
48 using then_sndr_t = stdexec::transform_sender_result_t<
49 decltype(stdexec::then(std::declval<schd_sndr_t>(), std::declval<functor_t>())),
50 stdexec::env<>
51 >;
52
55 static_assert(std::same_as<Kokkos::Execution::ExecutionSpaceImpl::exec_of_t<then_sndr_t>, TEST_EXECUTION_SPACE>);
56
59
61 using policy_t = typename then_sndr_t::closure_t::policy_t;
62 static_assert(std::same_as<typename policy_t::launch_bounds, Kokkos::LaunchBounds<1>>);
63
64 return true;
65}
66static_assert(test_sndr_traits());
67
72TEST_F(ThenTest, then_schedule) {
73 const view_s_t data(Kokkos::view_alloc(exec, "data - shared space"));
74
75 const context_t esc{exec};
76
77 auto chain = stdexec::schedule(esc.get_scheduler()) | THEN_INCREMENT(data) | THEN_INCREMENT(data);
78
79 using chain_t = decltype(chain);
80
82 static_assert(std::same_as<stdexec::__domain_of_t<stdexec::env_of_t<chain_t>>, stdexec::default_domain>);
83 static_assert(std::same_as<
84 stdexec::__detail::__completing_domain_t<stdexec::set_value_t, chain_t>,
86 >);
87
89 static_assert(std::same_as<
90 decltype(stdexec::get_completion_scheduler<stdexec::set_value_t>(stdexec::get_env(chain))),
92 >);
93
94 ASSERT_THAT(
95 recorder_listener_t::record([chain = std::move(chain)]() mutable { stdexec::sync_wait(std::move(chain)); }),
96 testing::ElementsAre(
100
101 ASSERT_EQ(data(), 2);
102}
103
108TEST_F(ThenTest, then_starts_on) {
109 const view_s_t data(Kokkos::view_alloc(exec, "data - shared space"));
110
111 const context_t esc{exec};
112
114 auto chain = stdexec::just() | THEN_INCREMENT(data) | THEN_INCREMENT(data);
115
119 using chain_t = decltype(chain);
120
123 chain_t,
124 stdexec::__mset<stdexec::set_value_t(), stdexec::set_error_t(std::exception_ptr)>
125 >);
126
127 static_assert(
128 std::same_as<stdexec::__completion_domain_of_t<stdexec::set_value_t, chain_t>, stdexec::indeterminate_domain<>>);
129
131 auto starts_on = stdexec::starts_on(esc.get_scheduler(), std::move(chain));
132
133 using starts_on_t = decltype(starts_on);
134
137 static_assert(std::same_as<
138 decltype(stdexec::get_completion_scheduler<stdexec::set_value_t>(stdexec::get_env(starts_on))),
140 >);
141
142 static_assert(std::same_as<
143 std::invoke_result_t<stdexec::get_completion_signatures_t, starts_on_t, stdexec::env<>>,
144 stdexec::completion_signatures<stdexec::set_value_t(), stdexec::set_error_t(std::exception_ptr)>
145 >);
146
147 ASSERT_EQ(data(), 0) << "Eager execution is not allowed.";
148
149 ASSERT_THAT(
150 recorder_listener_t::record(
151 [starts_on = std::move(starts_on)]() mutable { stdexec::sync_wait(std::move(starts_on)); }),
152 testing::ElementsAre(
156
157 ASSERT_EQ(data(), 2);
158}
159
167TEST_F(ThenTest, error_propagates) {
168 const view_s_t data(Kokkos::view_alloc(exec, "data - shared space"));
169
170 const context_t esc{exec};
171
172 stdexec::sender auto sndr = stdexec::schedule(esc.get_scheduler()) | THEN_INCREMENT(data)
174 | stdexec::then(KOKKOS_LAMBDA() {
175 Kokkos::abort("The value channel should be used at this point.");
176 });
177
178 ASSERT_EQ(data(), 0) << "Eager execution is not allowed.";
179
180 ASSERT_THAT(
181 recorder_listener_t::record([sndr = std::move(sndr)]() mutable {
182 ASSERT_THAT(
183 Tests::Utils::Functors::MutableMoveToSyncWait{.sndr = std::move(sndr)},
184 testing::ThrowsMessage<std::runtime_error>(
185 testing::HasSubstr("ThrowsWhenCopied: Throwing in copy constructor!")));
186 }),
187 testing::ElementsAre(
188 MATCHER_FOR_BEGIN_PFOR(exec, dispatch_label(exec, "then")), // Increment: succeeds
189 MATCHER_FOR_BEGIN_PFOR(exec, dispatch_label(exec, "then")), // ThrowsWhenCopied: throws on copy
191
192 ASSERT_EQ(data(), 1);
193}
194
200TEST_F(ThenTest, then_lifetime) {
202 const context_t esc{exec};
203
205 auto create_chain_in_scope = [&]() {
206 const view_s_t data(Kokkos::view_alloc("data - shared space", exec));
207
208 return stdexec::schedule(esc.get_scheduler()) | THEN_INCREMENT(data) | THEN_INCREMENT(data);
209 };
210
212 auto run_test = [&]() {
213 auto chain = create_chain_in_scope();
214
215 using chain_t = decltype(chain);
216
218 static_assert(std::same_as<stdexec::__domain_of_t<stdexec::env_of_t<chain_t>>, stdexec::default_domain>);
219 static_assert(std::same_as<
220 stdexec::__detail::__completing_domain_t<stdexec::set_value_t, chain_t>,
222 >);
223
225 static_assert(std::same_as<
226 decltype(stdexec::get_completion_scheduler<stdexec::set_value_t>(stdexec::get_env(chain))),
228 >);
229
230 stdexec::sync_wait(std::move(chain));
231 };
232
233 ASSERT_THAT(
234 recorder_listener_t::record(run_test),
237 testing::Field(
239 testing::Field(
240 &Kokkos::utils::callbacks::AllocDescriptor::name, testing::StrEq("data - shared space")))),
245 testing::Field(
247 testing::Field(
248 &Kokkos::utils::callbacks::AllocDescriptor::name, testing::StrEq("data - shared space"))))));
249}
250
252consteval bool test_sndr_no_throw_transformable() {
253 using sndr_then_t =
254 decltype(stdexec::schedule(std::declval<typename ThenTest::scheduler_t>()) | stdexec::then(Tests::Utils::Functors::NoOp<false, false, false>{}));
255
256 static_assert(std::same_as<
257 stdexec::__demangle_t<sndr_then_t>,
259 stdexec::then_t,
262 >
263 >);
264
265 static_assert(stdexec::__detail::__has_nothrow_transform_sender<
267 stdexec::set_value_t,
268 sndr_then_t&&,
269 stdexec::env<>
270 >);
271
272 using sndr_then_maythrow_on_move_t =
273 decltype(stdexec::schedule(std::declval<typename ThenTest::scheduler_t>()) | stdexec::then(Tests::Utils::Functors::NoOp<false, false, true>{}));
274
275 static_assert(!stdexec::__detail::__has_nothrow_transform_sender<
277 stdexec::set_value_t,
278 sndr_then_maythrow_on_move_t&&,
279 stdexec::env<>
280 >);
281
282 return true;
283}
284static_assert(test_sndr_no_throw_transformable());
285
286} // namespace Tests::ExecutionSpaceImpl
constexpr std::string dispatch_label(const Exec &, Label &&label)
Get the dispatch label from Exec and label.
#define MATCHER_FOR_BEGIN_PFOR(_exec_, _label_)
#define MATCHER_FOR_BEGIN_FENCE(_exec_, _label_)
typename recorder_listener_t::event_variant_t variant_t
Definition test_then.cpp:38
RecorderListener< EventDiscardMatcher< TEST_EXECUTION_SPACE >, BeginFenceEvent, BeginParallelForEvent, AllocateDataEvent, DeallocateDataEvent > recorder_listener_t
Definition test_then.cpp:31
Concept for a sender whose completion scheduler is Kokkos::Execution::ExecutionSpaceImpl::Scheduler.
Concept that constrains the type of a sender that dispatches a functor for execution.
#define THEN_INCREMENT(_data_)
Add a then using Tests::Utils::Functors::Increment that may throw. // NOLINTNEXTLINE(cppcoreguideline...
Definition increment.hpp:35
auto AAllocateDataEvent(Matchers &&... matchers)
auto ADeallocateDataEvent(Matchers &&... matchers)
auto ContainsInOrder(Matchers &&... matchers)
consteval bool test_sndr_no_throw_transformable()
Definition test_bulk.cpp:71
consteval bool test_sndr_traits()
Definition test_bulk.cpp:38
typename stdexec::__basic_sender< Args... >::type basic_sender_t
See https://github.com/NVIDIA/stdexec/pull/1873#discussion_r2834863237.
Definition stdexec.hpp:10
Matcher to filter out events that are just noise for tests.
auto get_scheduler() const noexcept -> ExecutionSpaceImpl::Scheduler< Exec >
decltype(std::declval< const context_t >().get_scheduler()) scheduler_t
Definition context.hpp:26
decltype(stdexec::schedule(std::declval< scheduler_t >())) schedule_sender_t
Definition context.hpp:27
Kokkos::Execution::ExecutionSpaceContext< Exec > context_t
Definition context.hpp:25
This helper struct throws when copy constructed.