4#include "exec/single_thread_context.hpp"
39using namespace Kokkos::utils::callbacks;
55TEST(WhenAll, no_branch) {
56 auto sndr = stdexec::when_all();
58 static_assert(std::same_as<stdexec::tag_of_t<
decltype(sndr)>, stdexec::just_t>);
60 static_assert(!stdexec::dependent_sender<
decltype(sndr)>);
63 stdexec::get_completion_signatures<decltype(sndr)>()
64 == stdexec::completion_signatures<stdexec::set_value_t()>{});
66 ASSERT_TRUE(stdexec::sync_wait(std::move(sndr)).has_value());
70TEST(WhenAll, single_branch) {
71 auto sndr = stdexec::just(42);
73 static_assert(std::same_as<
decltype(stdexec::when_all(sndr)),
decltype(sndr)>);
74 static_assert(std::same_as<
75 decltype(stdexec::when_all(std::move(sndr))),
79 auto&& w_a = stdexec::when_all(sndr);
80 ASSERT_NE(std::addressof(w_a), std::addressof(sndr));
81 sndr = stdexec::just(56);
82 const auto result = stdexec::sync_wait(std::move(w_a));
83 ASSERT_TRUE(result.has_value());
84 ASSERT_EQ(std::get<0>(*result), 42);
86 std::get<0>(*stdexec::sync_wait(stdexec::when_all(std::move(sndr)))), 56);
89 using just_not_copy_constructible_t =
decltype(stdexec::just(std::make_unique<int>(0)));
90 static_assert(!std::copy_constructible<just_not_copy_constructible_t>);
91 static_assert(!std::invocable<const stdexec::when_all_t&, just_not_copy_constructible_t&>);
92 static_assert(std::invocable<const stdexec::when_all_t&, just_not_copy_constructible_t&&>);
108 const view_s_t data(Kokkos::view_alloc(
exec,
"data - shared space"));
114 static_assert(std::same_as<
115 decltype(stdexec::get_completion_domain<stdexec::set_value_t>(stdexec::get_env(sndr))),
119 static_assert(std::same_as<stdexec::tag_of_t<
decltype(sndr)>, stdexec::then_t>);
122 ASSERT_EQ(data(), 0) <<
"Eager execution is not allowed.";
126 testing::ElementsAre(
130 ASSERT_EQ(data(), 1);
144 const view_s_t data(Kokkos::view_alloc(
exec,
"data - shared space"));
148 auto sndr = stdexec::when_all(
151 static_assert(std::same_as<
152 decltype(stdexec::get_completion_domain<stdexec::set_value_t>(stdexec::get_env(sndr))),
160 ASSERT_EQ(data(), 0) <<
"Eager execution is not allowed.";
166 ASSERT_THAT(recorded_events, [&]() {
168 return testing::ElementsAre(
173 return testing::ElementsAre(
179 ASSERT_EQ(data(), 1);
193TEST_F(
WhenAllTest, schedule_sender_and_single_branch_followed_by_self) {
194 const view_s_t data(Kokkos::view_alloc(
exec,
"data - shared space"));
198 auto sndr = stdexec::when_all(
203 ASSERT_EQ(data(), 0) <<
"Eager execution is not allowed.";
207 testing::ElementsAre(
212 ASSERT_EQ(data(), 2);
227TEST_F(
WhenAllTest, schedule_sender_and_single_mixed_branch_followed_by_self) {
228 const view_s_t data(Kokkos::view_alloc(
exec,
"data - shared space"));
231 experimental::execution::single_thread_context stc{};
233 auto sndr = stdexec::when_all(
234 stdexec::schedule(stc.get_scheduler()),
236 | stdexec::continues_on(stc.get_scheduler()) |
THEN_INCREMENT(data))
239 ASSERT_EQ(data(), 0) <<
"Eager execution is not allowed.";
245 testing::ElementsAre(
251 ASSERT_EQ(data(), 3);
265TEST_F(
WhenAllTest, schedule_sender_and_single_branch_followed_by_other_and_finish_on_self) {
266 const view_s_t data(Kokkos::view_alloc(
exec,
"data - shared space"));
269 experimental::execution::single_thread_context stc{};
271 auto sndr = stdexec::when_all(
274 | stdexec::continues_on(stc.get_scheduler()) |
THEN_INCREMENT(data)
277 ASSERT_EQ(data(), 0) <<
"Eager execution is not allowed.";
283 ASSERT_THAT(recorded_events, [&]() {
285 return testing::ElementsAre(
292 return testing::ElementsAre(
300 ASSERT_EQ(data(), 3);
314 const view_s_t data(Kokkos::view_alloc(
"data - shared space"));
317 experimental::execution::single_thread_context stc{};
319 auto w_a = stdexec::when_all(
326 decltype(stdexec::get_completion_domain<stdexec::set_value_t>(stdexec::get_env(w_a), stdexec::env<>{})),
332 ASSERT_EQ(data(), 0) <<
"Eager execution is not allowed.";
338 testing::ElementsAre(
343 ASSERT_EQ(data(), 3);
357 const view_s_t data(Kokkos::view_alloc(
exec,
"data - shared space"));
359 const auto [exec_A, exec_B] = Kokkos::Experimental::partition_space(
exec, 1, 1);
361 const context_t esc_A{exec_A}, esc_B{exec_B};
363 auto sndr = stdexec::when_all(
368 ASSERT_EQ(data(), 0) <<
"Eager execution is not allowed.";
375 testing::ElementsAre(
381 ASSERT_THAT(recorded_events, [&]() {
383 return testing::ElementsAre(
392 return testing::ElementsAre(
402 ASSERT_EQ(data(), 3);
419 const view_s_t data(Kokkos::view_alloc(
"data - shared space"));
424 const context_h_t esc_h{exec_h};
426 auto sndr = stdexec::when_all(
431 ASSERT_EQ(data(), 0) <<
"Eager execution is not allowed.";
438 testing::ElementsAre(
444 ASSERT_THAT(recorded_events, [&]() {
446 return testing::ElementsAre(
454 return testing::ElementsAre(
464 ASSERT_EQ(data(), 3);
478TEST_F(
WhenAllTest, two_mixed_branches_followed_by_other_and_finish_on_self) {
479 const view_s_t data(Kokkos::view_alloc(
"data - shared space"));
482 experimental::execution::single_thread_context stc{};
484 auto sndr = stdexec::when_all(
486 | stdexec::continues_on(stc.get_scheduler()),
488 | stdexec::continues_on(stc.get_scheduler()) |
THEN_INCREMENT(data)
491 ASSERT_EQ(data(), 0) <<
"Eager execution is not allowed.";
497 testing::ElementsAre(
503 ASSERT_EQ(data(), 4);
524 const view_s_t data(Kokkos::view_alloc(
"data - shared space"));
527 experimental::execution::single_thread_context stc{};
529 auto sndr = stdexec::when_all(
539 ASSERT_EQ(data(), 0) <<
"Eager execution is not allowed.";
545 ASSERT_THAT(recorded_events, [&]() {
547 return testing::ElementsAre(
555 return testing::ElementsAre(
564 ASSERT_EQ(data(), 4);
579 const auto [exec_A, exec_B, exec_C] = Kokkos::Experimental::partition_space(
exec, 1, 1, 1);
581 const context_t esc_A{exec_A}, esc_B{exec_B}, esc_C{exec_C};
584 auto br_B = ::stdexec::schedule(esc_B.get_scheduler()) |
THEN_LABELED_PFOR(TEST_EXECUTION_SPACE,
'B');
585 auto br_C = ::stdexec::schedule(esc_C.get_scheduler()) |
THEN_LABELED_PFOR(TEST_EXECUTION_SPACE,
'C');
587 auto when_AB_then_D = ::stdexec::when_all(std::move(br_A), std::move(br_B))
590 auto sndr = ::stdexec::when_all(std::move(when_AB_then_D), std::move(br_C));
597 testing::ElementsAre(
605 ASSERT_THAT(recorded_events, [&]() {
607 return testing::ElementsAre(
619 return testing::ElementsAre(
645 const view_s_t data(Kokkos::view_alloc(
exec,
"data - shared space"));
647 constexpr size_t num_branches = 6;
649 unsigned int counter_start = 0, counter_after_stc = 0;
650 std::array<unsigned int, num_branches> order_start{}, order_after_stc{};
652 const auto [exec_A, exec_B, exec_C, exec_D, exec_E, exec_F] =
653 Kokkos::Experimental::partition_space(
exec, 1, 1, 1, 1, 1, 1);
655 using view_um_h_t = Kokkos::View<unsigned int, Kokkos::HostSpace, Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
658#define DEFINE_ONE_BRANCH(_letter_, _id_) \
659 const context_t esc_##_letter_{exec_##_letter_}; \
660 experimental::execution::single_thread_context stc_##_letter_{}; \
661 auto br_##_letter_ = stdexec::just() \
663 increment_and_memorize_t{ \
664 .counter = view_um_h_t{std::addressof(counter_start)}, \
665 .value = view_um_h_t{std::addressof(order_start.at(_id_))}}) \
666 | stdexec::continues_on(stc_##_letter_.get_scheduler()) \
668 increment_and_memorize_t{ \
669 .counter = view_um_h_t{std::addressof(counter_after_stc)}, \
670 .value = view_um_h_t{std::addressof(order_after_stc.at(_id_))}}) \
671 | stdexec::continues_on(esc_##_letter_.get_scheduler()) | THEN_INCREMENT_ATOMIC(Device, data);
680 auto sndr = stdexec::when_all(
681 std::move(br_A), std::move(br_B), std::move(br_C), std::move(br_D), std::move(br_E), std::move(br_F));
683 ASSERT_EQ(data(), 0) <<
"Eager execution is not allowed.";
687 stdexec::sync_wait(std::move(sndr));
689 ASSERT_EQ(counter_start, num_branches);
690 ASSERT_EQ(counter_after_stc, num_branches);
692 ASSERT_EQ(data(), num_branches);
695 ASSERT_THAT(order_start, testing::ElementsAre(0, 1, 2, 3, 4, 5));
700#define SHOW_ONE_BRANCH_ORDER_AFTER_STC(_letter_, _id_) \
701 SCOPED_TRACE(testing::Message() << "Branch " #_letter_ " order after 'stc' is " << order_after_stc.at(_id_));
711 ASSERT_THAT(order_after_stc, testing::UnorderedElementsAre(0, 1, 2, 3, 4, 5));
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_)
RecorderListener< EventDiscardMatcher< TEST_EXECUTION_SPACE >, BeginFenceEvent, BeginParallelForEvent, Kokkos::Execution::Impl::RecordEvent, Kokkos::Execution::Impl::WaitEvent > recorder_listener_t
Concept for a sender whose completion scheduler is Kokkos::Execution::ExecutionSpaceImpl::Scheduler.
#define KOKKOS_EXECUTION_THREADS_THROWS_ON_SYNC_WAIT_ASSERT_AND_SKIP(_sndr_)
Kokkos::DefaultHostExecutionSpace host_execution_space
#define DEFINE_ONE_BRANCH(_letter_, _id_)
#define SHOW_ONE_BRANCH_ORDER_AFTER_STC(_letter_, _id_)
#define KOKKOS_EXECUTION_STDEXEC_PRAGMA_DIAGNOSTIC_IGNORED
Basic list of ignored diagnostics when including anything from stdexec.
#define THEN_INCREMENT(_data_)
Add a then using Tests::Utils::Functors::Increment that may throw. // NOLINTNEXTLINE(cppcoreguideline...
#define THEN_INCREMENT_ATOMIC(_scope_, _data_)
Same as THEN_INCREMENT, using Tests::Utils::atomic_fetch_add. // NOLINTNEXTLINE(cppcoreguidelines-mac...
#define THEN_LABELED_PFOR(_exec_, _id_)
Add a Kokkos::Execution::parallel_for using Tests::Utils::Functors::Labeled. // NOLINTNEXTLINE(cppcor...
constexpr check_rcvr_env_queryable_with_t< false, Queries... > check_rcvr_env_not_queryable_with
auto record_sync_wait(Sndr &&sndr)
bool are_same_instances(const Exec &exec, const OtherExec &other_exec)
Matcher to filter out events that are just noise for tests.
Execution context using a Kokkos execution space under the hood.
auto get_scheduler() const noexcept -> ExecutionSpaceImpl::Scheduler< Exec >
Event to be sent to Kokkos::utils::callbacks::dispatch when calling record.
Event to be sent to Kokkos::utils::callbacks::dispatch when calling wait.
Kokkos::View< value_t, Kokkos::SharedSpace > view_s_t
Kokkos::Execution::ExecutionSpaceContext< Exec > context_t