kokkos-execution 0.0.1
Loading...
Searching...
No Matches
test_then.cpp
Go to the documentation of this file.
3
5
16
28
30
31using namespace Kokkos::utils::callbacks;
32
48
50consteval bool test_sndr_traits() {
52 using schd_sndr_t = typename ThenTest::schedule_sender_t;
53
56 using then_sndr_t = stdexec::transform_sender_result_t<
57 decltype(stdexec::then(std::declval<schd_sndr_t>(), std::declval<functor_t>())),
58 stdexec::env<>
59 >;
60
63 static_assert(std::same_as<Kokkos::Execution::Impl::exec_of_t<then_sndr_t>, TEST_EXECUTION_SPACE>);
64
67
69 using policy_t = typename then_sndr_t::closure_t::policy_t;
70 static_assert(std::same_as<typename policy_t::launch_bounds, Kokkos::LaunchBounds<1>>);
71
72 return true;
73}
74static_assert(test_sndr_traits());
75
78 typename ThenTest::scheduler_t,
79 stdexec::then_t,
81>());
82
87TEST_F(ThenTest, then_schedule) {
88 const view_s_t data(Kokkos::view_alloc(exec, "data - shared space"));
89
90 const context_t esc{exec};
91
92 auto chain = stdexec::schedule(esc.get_scheduler()) | THEN_INCREMENT(data) | THEN_INCREMENT(data);
93
94 using chain_t = decltype(chain);
95
97 static_assert(std::same_as<stdexec::__domain_of_t<stdexec::env_of_t<chain_t>>, stdexec::default_domain>);
98 static_assert(std::same_as<
99 stdexec::__detail::__completing_domain_t<stdexec::set_value_t, chain_t>,
101 >);
102
104 static_assert(std::same_as<
105 decltype(stdexec::get_completion_scheduler<stdexec::set_value_t>(stdexec::get_env(chain))),
107 >);
108
109 ASSERT_THAT(
111 testing::ElementsAre(
115
116 ASSERT_EQ(data(), 2);
117}
118
123TEST_F(ThenTest, then_starts_on) {
124 const view_s_t data(Kokkos::view_alloc(exec, "data - shared space"));
125
126 const context_t esc{exec};
127
129 auto chain = stdexec::just() | THEN_INCREMENT(data) | THEN_INCREMENT(data);
130
134 using chain_t = decltype(chain);
135
138 chain_t,
139 stdexec::__mset<stdexec::set_value_t(), stdexec::set_error_t(std::exception_ptr)>
140 >);
141
142 static_assert(
143 std::same_as<stdexec::__completion_domain_of_t<stdexec::set_value_t, chain_t>, stdexec::indeterminate_domain<>>);
144
146 auto starts_on = stdexec::starts_on(esc.get_scheduler(), std::move(chain));
147
148 using starts_on_t = decltype(starts_on);
149
152 static_assert(std::same_as<
153 decltype(stdexec::get_completion_scheduler<stdexec::set_value_t>(stdexec::get_env(starts_on))),
155 >);
156
157 static_assert(std::same_as<
158 std::invoke_result_t<stdexec::get_completion_signatures_t, starts_on_t, stdexec::env<>>,
159 stdexec::completion_signatures<stdexec::set_value_t(), stdexec::set_error_t(std::exception_ptr)>
160 >);
161
162 ASSERT_EQ(data(), 0) << "Eager execution is not allowed.";
163
164 const auto recorded_events = Tests::Utils::record_sync_wait<recorder_listener_t>(std::move(starts_on));
165
166 ASSERT_THAT(recorded_events, [&]() {
168 return testing::ElementsAre(
172 MATCHER_FOR_WAIT_EVENT(recorded_events.at(2)));
173 } else {
174 return testing::ElementsAre(
177 MATCHER_FOR_BEGIN_FENCE(exec, dispatch_label(exec, "after dispatch")));
178 }
179 }());
180
181 ASSERT_EQ(data(), 2);
182}
183
191TEST_F(ThenTest, error_propagates) {
192 const view_s_t data(Kokkos::view_alloc(exec, "data - shared space"));
193
194 const context_t esc{exec};
195
196 stdexec::sender auto sndr = stdexec::schedule(esc.get_scheduler()) | THEN_INCREMENT(data)
198 | stdexec::then(KOKKOS_LAMBDA() {
199 Kokkos::abort("The value channel should be used at this point.");
200 });
201
202 ASSERT_EQ(data(), 0) << "Eager execution is not allowed.";
203
204 ASSERT_THAT(
205 recorder_listener_t::record([sndr = std::move(sndr)]() mutable {
206 ASSERT_THAT(
207 Tests::Utils::Functors::MutableMoveToSyncWait{.sndr = std::move(sndr)},
208 testing::ThrowsMessage<std::runtime_error>(
209 testing::HasSubstr("ThrowsWhenCopied: Throwing in copy constructor!")));
210 }),
211 testing::ElementsAre(
212 MATCHER_FOR_BEGIN_PFOR(exec, dispatch_label(exec, "then")), // Increment: succeeds
213 MATCHER_FOR_BEGIN_PFOR(exec, dispatch_label(exec, "then")), // ThrowsWhenCopied: throws on copy
215
216 ASSERT_EQ(data(), 1);
217}
218
224TEST_F(ThenTest, then_lifetime) {
226 const context_t esc{exec};
227
229 auto create_chain_in_scope = [&]() {
230 const view_s_t data(Kokkos::view_alloc("data - shared space", exec));
231
232 return stdexec::schedule(esc.get_scheduler()) | THEN_INCREMENT(data) | THEN_INCREMENT(data);
233 };
234
236 auto run_test = [&]() {
237 auto chain = create_chain_in_scope();
238
239 using chain_t = decltype(chain);
240
242 static_assert(std::same_as<stdexec::__domain_of_t<stdexec::env_of_t<chain_t>>, stdexec::default_domain>);
243 static_assert(std::same_as<
244 stdexec::__detail::__completing_domain_t<stdexec::set_value_t, chain_t>,
246 >);
247
249 static_assert(std::same_as<
250 decltype(stdexec::get_completion_scheduler<stdexec::set_value_t>(stdexec::get_env(chain))),
252 >);
253
254 stdexec::sync_wait(std::move(chain));
255 };
256
257 ASSERT_THAT(
258 recorder_listener_t::record(run_test),
261 testing::Field(
263 testing::Field(
264 &Kokkos::utils::callbacks::AllocDescriptor::name, testing::StrEq("data - shared space")))),
269 testing::Field(
271 testing::Field(
272 &Kokkos::utils::callbacks::AllocDescriptor::name, testing::StrEq("data - shared space"))))));
273}
274
276consteval bool test_sndr_nothrow_transformable() {
277 using sndr_then_t =
278 decltype(stdexec::schedule(std::declval<typename ThenTest::scheduler_t>()) | stdexec::then(Tests::Utils::Functors::NoOp<false, false, false>{}));
279
280 static_assert(std::same_as<
281 stdexec::__demangle_t<sndr_then_t>,
283 stdexec::then_t,
286 >
287 >);
288
289 static_assert(stdexec::__detail::__has_nothrow_transform_sender<
291 stdexec::set_value_t,
292 sndr_then_t&&,
293 stdexec::env<>
294 >);
295
296 using sndr_then_maythrow_on_move_t =
297 decltype(stdexec::schedule(std::declval<typename ThenTest::scheduler_t>()) | stdexec::then(Tests::Utils::Functors::NoOp<false, false, true>{}));
298
299 static_assert(!stdexec::__detail::__has_nothrow_transform_sender<
301 stdexec::set_value_t,
302 sndr_then_maythrow_on_move_t&&,
303 stdexec::env<>
304 >);
305
306 return true;
307}
308static_assert(test_sndr_nothrow_transformable());
309
311TEST_F(ThenTest, forwarding_env) {
312 const view_s_t data(Kokkos::view_alloc(exec, "data - shared space"));
313
314 std::atomic<size_t> count = 0;
315
316 int value;
317
318 const context_t esc{exec};
319
320 stdexec::sender auto sndr =
321 stdexec::read_env(stdexec::get_allocator)
322 | stdexec::then([&value](auto allocator) { value = Tests::Utils::round_trip_allocate(allocator, 42); })
323 | stdexec::continues_on(esc.get_scheduler())
325 | stdexec::write_env(stdexec::prop{stdexec::get_allocator, Tests::Utils::TrackingAllocator<int>{&count}});
326
327 ASSERT_EQ(data(), 0) << "Eager execution is not allowed.";
328
329 const auto recorded_events = Tests::Utils::record_sync_wait<recorder_listener_t>(std::move(sndr));
330
331 ASSERT_THAT(recorded_events, [&]() {
333 return testing::ElementsAre(
336 MATCHER_FOR_WAIT_EVENT(recorded_events.at(1)));
337 } else {
338 return testing::ElementsAre(
340 MATCHER_FOR_BEGIN_FENCE(exec, dispatch_label(exec, "after dispatch")));
341 }
342 }());
343
344 ASSERT_EQ(data(), 1);
345
346 ASSERT_EQ(value, 42);
347 ASSERT_EQ(count, 1);
348}
349
350} // namespace Tests::ExecutionSpaceImpl
constexpr std::string dispatch_label(const Exec &, Label &&label)
Get the dispatch label from Exec and label.
#define MATCHER_FOR_WAIT_EVENT(_record_event_variant_)
#define MATCHER_FOR_BEGIN_PFOR(_exec_, _label_)
#define MATCHER_FOR_RECORD_EVENT(_exec_)
#define MATCHER_FOR_BEGIN_FENCE(_exec_, _label_)
typename recorder_listener_t::event_variant_t variant_t
Definition test_then.cpp:46
RecorderListener< EventDiscardMatcher< TEST_EXECUTION_SPACE >, BeginFenceEvent, BeginParallelForEvent, AllocateDataEvent, DeallocateDataEvent, Kokkos::Execution::Impl::RecordEvent, Kokkos::Execution::Impl::WaitEvent > recorder_listener_t
Definition test_then.cpp:37
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_traits()
Definition test_bulk.cpp:49
consteval bool test_sndr_nothrow_transformable()
Definition test_bulk.cpp:83
typename stdexec::__basic_sender< Args... >::type basic_sender_t
See https://github.com/NVIDIA/stdexec/pull/1873#discussion_r2834863237.
Definition stdexec.hpp:12
auto record_sync_wait(Sndr &&sndr)
Definition sync_wait.hpp:14
consteval bool check_continues_on_after_just_stopped()
constexpr check_rcvr_env_queryable_with_t< true, Queries... > check_rcvr_env_queryable_with
auto round_trip_allocate(Allocator &allocator, T &&value)
Matcher to filter out events that are just noise for tests.
auto get_scheduler() const noexcept -> ExecutionSpaceImpl::Scheduler< Exec >
Event to be sent to Kokkos::utils::callbacks::dispatch when calling record.
Definition event.hpp:52
Event to be sent to Kokkos::utils::callbacks::dispatch when calling wait.
Definition event.hpp:73
decltype(std::declval< const context_t >().get_scheduler()) scheduler_t
Definition context.hpp:28
decltype(stdexec::schedule(std::declval< scheduler_t >())) schedule_sender_t
Definition context.hpp:29
Kokkos::Execution::ExecutionSpaceContext< Exec > context_t
Definition context.hpp:27
This helper struct throws when copy constructed.
A minimal tracking allocator.