diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 586f851b..12bd5624 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -30,6 +30,7 @@ set(EXAMPLES intro_5_consumer playground sender_demo + sleep_sort stackoverflow stopping stop_token @@ -41,6 +42,10 @@ if(BEMAN_USE_MODULES) list(APPEND EXAMPLES modules_and_header) endif() +if(BEMAN_EXECUTION_WITH_DEFAULT_PARALLEL_SCHEDULER_BACKEND) + list(APPEND EXAMPLES async_inclusive_scan) +endif() + foreach(EXAMPLE ${EXAMPLES}) set(EXAMPLE_TARGET ${PROJECT_NAME}.${EXAMPLE}) add_executable(${EXAMPLE_TARGET}) diff --git a/examples/async_inclusive_scan.cpp b/examples/async_inclusive_scan.cpp new file mode 100644 index 00000000..82402de0 --- /dev/null +++ b/examples/async_inclusive_scan.cpp @@ -0,0 +1,69 @@ +// examples/async_inclusive_scan.cpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#ifdef BEMAN_HAS_IMPORT_STD +import std; +#else +#include +#include +#include +#include +#include +#include +#include +#endif +#ifdef BEMAN_HAS_MODULES +import beman.execution; +#else +#include +#endif + +namespace ex = beman::execution; + +namespace { +template Sentinel, + std::output_iterator> OutputIt> +ex::sender auto +async_inclusive_scan(Scheduler scheduler, std::size_t tile_count, ForwardIt first, Sentinel last, OutputIt dest) { + const std::size_t n = std::ranges::distance(first, last); + const std::size_t tile_size = (n + tile_count - 1) / tile_count; + return ex::just(std::vector(tile_count + 1)) | ex::let_value([=](std::vector& partials) { + return ex::schedule(scheduler) | + ex::bulk(ex::par, + tile_count, + [=, &partials](std::size_t i) { + auto start = i * tile_size; + auto end = std::min(n, (i + 1) * tile_size); + partials[i + 1] = + *std::ranges::prev(std::inclusive_scan(std::ranges::next(first, start), + std::ranges::next(first, end), + std::ranges::next(dest, start))); + }) | + ex::then( + [&partials] { std::inclusive_scan(partials.begin(), partials.end(), partials.begin()); }) | + ex::bulk(ex::par, + tile_count, + [=, &partials](std::size_t i) { + auto start = i * tile_size; + auto end = std::min(n, (i + 1) * tile_size); + std::for_each(std::ranges::next(dest, start), + std::ranges::next(dest, end), + [&](int& e) { e = partials[i] + e; }); + }) | + ex::then([=] { return std::ranges::next(dest, n); }); + }); +} +} // namespace + +auto main() -> int { + constexpr std::size_t n = 32uz; + ex::parallel_scheduler scheduler = ex::get_parallel_scheduler(); + std::vector input(n); + std::vector output(input.size()); + std::iota(input.begin(), input.end(), 1); // NOLINT + auto _ = ex::sync_wait(async_inclusive_scan(scheduler, 4, input.begin(), input.end(), output.begin())).value(); + std::println("{}", output); +} diff --git a/examples/intro_timer.hpp b/examples/intro_timer.hpp index 25ec0e01..a71d6ce0 100644 --- a/examples/intro_timer.hpp +++ b/examples/intro_timer.hpp @@ -123,8 +123,8 @@ struct intro::timer { auto run() { return run_sender{this}; } - template - auto resume_after(std::chrono::duration d) { + template + auto resume_after(std::chrono::duration d) { auto ms(std::chrono::duration_cast(d)); return sender{this, ms}; } diff --git a/examples/sleep_sort.cpp b/examples/sleep_sort.cpp new file mode 100644 index 00000000..ded255c2 --- /dev/null +++ b/examples/sleep_sort.cpp @@ -0,0 +1,45 @@ +// examples/sleep_sort.cpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#ifdef BEMAN_HAS_IMPORT_STD +import std; +#else +#include +#include +#include +#include +#endif +#ifdef BEMAN_HAS_MODULES +import beman.execution; +#else +#include +#endif +#include "intro_timer.hpp" + +namespace ex = beman::execution; + +namespace { +auto sleep_sort(std::span input) -> ex::task> { + intro::timer timer; + std::vector result; + result.reserve(input.size()); + ex::simple_counting_scope scope; + for (auto i : input) { + ex::spawn(timer.resume_after(std::chrono::milliseconds(i)) | + ex::then([i, &result]() noexcept { result.push_back(i); }), + scope.get_token()); + } + auto sch = co_await ex::read_env(ex::get_start_scheduler); + co_await ex::when_all(timer.run() | ex::write_env(ex::prop{ex::get_delegation_scheduler, sch}), scope.join()); + co_return result; +} +} // namespace + +auto main() -> int { + auto tick = std::chrono::steady_clock::now(); + std::vector input{5, 10, 1, 3, 4, 2, 9, 11, 8, 6, 7, 3, 4}; + auto [result] = ex::sync_wait(sleep_sort(input)).value(); + auto tock = std::chrono::steady_clock::now(); + std::println("result = {}, take {}", result, std::chrono::duration_cast(tock - tick)); +} diff --git a/include/beman/execution/detail/affine.hpp b/include/beman/execution/detail/affine.hpp index f6f1a138..cb6d556d 100644 --- a/include/beman/execution/detail/affine.hpp +++ b/include/beman/execution/detail/affine.hpp @@ -78,7 +78,7 @@ namespace beman::execution::detail { * scheduler obtained the receiver's environment. The get_start_scheduler query is used * to obtain the scheduler on which the sender gets started. */ -struct affine_t : ::beman::execution::sender_adaptor_closure { +struct affine_t { /** * @brief Adapt a sender with affine. * diff --git a/include/beman/execution/detail/bulk.hpp b/include/beman/execution/detail/bulk.hpp index 63c2ff13..a624f3e4 100644 --- a/include/beman/execution/detail/bulk.hpp +++ b/include/beman/execution/detail/bulk.hpp @@ -19,8 +19,11 @@ import beman.execution.detail.basic_sender; import beman.execution.detail.completion_signatures; import beman.execution.detail.completion_signatures_of_t; import beman.execution.detail.default_impls; +import beman.execution.detail.env; import beman.execution.detail.execution_policy; import beman.execution.detail.forward_like; +import beman.execution.detail.fwd_env; +import beman.execution.detail.get_completion_signatures; import beman.execution.detail.make_sender; import beman.execution.detail.meta.combine; import beman.execution.detail.meta.unique; @@ -28,6 +31,7 @@ import beman.execution.detail.product_type; import beman.execution.detail.sender; import beman.execution.detail.sender_adaptor_closure; import beman.execution.detail.sender_for; +import beman.execution.detail.sender_in; import beman.execution.detail.set_error; import beman.execution.detail.set_value; #else @@ -35,8 +39,11 @@ import beman.execution.detail.set_value; #include #include #include +#include #include #include +#include +#include #include #include #include @@ -44,6 +51,7 @@ import beman.execution.detail.set_value; #include #include #include +#include #include #include #endif @@ -129,21 +137,26 @@ struct bulk_algo_t { template struct get_signatures; template + requires ::beman::execution::sender_in...> struct get_signatures< ::beman::execution::detail:: basic_sender, Sender>, Env...> { - using type = typename ::beman::execution::detail::bulk_transform_signatures< - is_chunked, - F, - Shape, - ::beman::execution::completion_signatures_of_t>::type; + static consteval auto get() { + [[maybe_unused]] auto child_sigs = + ::beman::execution::get_completion_signatures...>(); + using child_sigs_t = decltype(child_sigs); + using type = typename ::beman::execution::detail:: + bulk_transform_signatures::type; + return type{}; + } }; public: template - static consteval auto get_completion_signatures() noexcept { - return typename get_signatures<::std::remove_cvref_t, Env...>::type{}; + requires requires { get_signatures<::std::remove_cvref_t, Env...>{}; } + static consteval auto get_completion_signatures() { + return get_signatures<::std::remove_cvref_t, Env...>::get(); } struct impls_for : ::beman::execution::detail::default_impls { @@ -212,7 +225,7 @@ struct bulk_t { } template <::beman::execution::detail::sender_for Sender, typename Env> - auto transform_sender(::beman::execution::set_value_t, Sender&& sndr, const Env&) const { + static auto transform_sender(::beman::execution::set_value_t, Sender&& sndr, const Env&) { auto data = ::beman::execution::detail::forward_like(sndr.template get<1>()); auto child = ::beman::execution::detail::forward_like(sndr.template get<2>()); @@ -223,23 +236,10 @@ struct bulk_t { return bulk_chunked_t{}(::std::move(child), policy, shape, - this->wrap_chunked<::std::remove_cvref_t>(::std::move(f))); + bulk_t::wrap_chunked<::std::remove_cvref_t>(::std::move(f))); } private: - template - struct get_signatures; - template - struct get_signatures<::beman::execution::detail:: - basic_sender, Sender>, - Env...> { - using type = typename ::beman::execution::detail::bulk_transform_signatures< - false, - F, - Shape, - ::beman::execution::completion_signatures_of_t>::type; - }; - template static auto wrap_chunked(Fn f) noexcept { return [f = ::std::move(f)](Shape begin, Shape end, Args&&... args) noexcept( @@ -250,10 +250,15 @@ struct bulk_t { }; } + template + using transformed_sender = decltype(bulk_t::transform_sender( + ::beman::execution::set_value, ::std::declval(), ::std::declval<::beman::execution::env<>>())); + public: - template - static consteval auto get_completion_signatures() noexcept { - return typename get_signatures<::std::remove_cvref_t, Env...>::type{}; + template <::beman::execution::sender Sender> + requires ::beman::execution::sender_in> + static consteval auto get_completion_signatures() { + return ::beman::execution::get_completion_signatures>(); } }; diff --git a/include/beman/execution/detail/continues_on.hpp b/include/beman/execution/detail/continues_on.hpp index 84a10684..d292619d 100644 --- a/include/beman/execution/detail/continues_on.hpp +++ b/include/beman/execution/detail/continues_on.hpp @@ -26,7 +26,6 @@ import beman.execution.detail.connect; import beman.execution.detail.connect_result_t; import beman.execution.detail.decayed_tuple; import beman.execution.detail.default_impls; -import beman.execution.detail.dependent_sender; import beman.execution.detail.env; import beman.execution.detail.env_of_t; import beman.execution.detail.error_types_of_t; @@ -67,7 +66,6 @@ import beman.execution.detail.start; #include #include #include -#include #include #include #include @@ -167,22 +165,20 @@ struct continues_on_t { template struct get_signatures; - template - requires(!::beman::execution::dependent_sender<::beman::execution::schedule_result_t>) - struct get_signatures< - ::beman::execution::detail::basic_sender<::beman::execution::detail::continues_on_t, Scheduler, Sender>> - : get_signatures> {}; - template - requires ::beman::execution::sender_in> + + template + requires ::beman::execution::sender_in<::beman::execution::schedule_result_t, + ::beman::execution::detail::fwd_env_t...> && + ::beman::execution::sender_in...> struct get_signatures< ::beman::execution::detail::basic_sender<::beman::execution::detail::continues_on_t, Scheduler, Sender>, - Env> { + Env...> { static consteval auto get() { - using env_t = ::beman::execution::detail::fwd_env_t; - [[maybe_unused]] auto child_sigs = ::beman::execution::get_completion_signatures(); + [[maybe_unused]] auto child_sigs = + ::beman::execution::get_completion_signatures...>(); [[maybe_unused]] auto sched_sigs = ::beman::execution::get_completion_signatures<::beman::execution::schedule_result_t, - env_t>(); + ::beman::execution::detail::fwd_env_t...>(); using child_sigs_t = decltype(child_sigs); using extra_sigs_t = ::beman::execution::detail::meta::filter; using error_completion = ::std::conditional_t< diff --git a/include/beman/execution/detail/into_variant.hpp b/include/beman/execution/detail/into_variant.hpp index bbd5874b..6d51375a 100644 --- a/include/beman/execution/detail/into_variant.hpp +++ b/include/beman/execution/detail/into_variant.hpp @@ -64,7 +64,7 @@ import beman.execution.detail.variant_or_empty; // ---------------------------------------------------------------------------- namespace beman::execution::detail { -struct into_variant_t : ::beman::execution::sender_adaptor_closure { +struct into_variant_t { template <::beman::execution::sender Sender> auto operator()(Sender&& sender) const { return ::beman::execution::detail::make_sender(*this, {}, ::std::forward(sender)); diff --git a/include/beman/execution/detail/on.hpp b/include/beman/execution/detail/on.hpp index f2091c69..e8e4900b 100644 --- a/include/beman/execution/detail/on.hpp +++ b/include/beman/execution/detail/on.hpp @@ -72,7 +72,7 @@ import beman.execution.detail.transform_sender; // ---------------------------------------------------------------------------- namespace beman::execution::detail { -struct on_t : ::beman::execution::sender_adaptor_closure { +struct on_t { template static auto dry_run(OutSndr&& out_sndr) noexcept { auto& [_, data, child] = out_sndr; diff --git a/include/beman/execution/detail/run_loop.hpp b/include/beman/execution/detail/run_loop.hpp index 0c5c50ca..5ef4e60c 100644 --- a/include/beman/execution/detail/run_loop.hpp +++ b/include/beman/execution/detail/run_loop.hpp @@ -117,7 +117,7 @@ class run_loop { run_loop* loop; - auto schedule() noexcept -> sender { return {this->loop}; } + auto schedule() const noexcept -> sender { return {this->loop}; } auto operator==(const scheduler&) const -> bool = default; static constexpr auto query(::beman::execution::get_forward_progress_guarantee_t) noexcept diff --git a/include/beman/execution/detail/schedule_from.hpp b/include/beman/execution/detail/schedule_from.hpp index de361e2b..15b13ad0 100644 --- a/include/beman/execution/detail/schedule_from.hpp +++ b/include/beman/execution/detail/schedule_from.hpp @@ -12,16 +12,20 @@ import std; #endif #ifdef BEMAN_HAS_MODULES import beman.execution.detail.child_type; +import beman.execution.detail.fwd_env; import beman.execution.detail.get_completion_signatures; import beman.execution.detail.make_sender; import beman.execution.detail.product_type; import beman.execution.detail.sender; +import beman.execution.detail.sender_in; #else #include +#include #include #include #include #include +#include #endif // ---------------------------------------------------------------------------- @@ -30,8 +34,11 @@ namespace beman::execution::detail { struct schedule_from_t { template + requires ::beman::execution::sender_in<::beman::execution::detail::child_type, + ::beman::execution::detail::fwd_env_t...> static consteval auto get_completion_signatures() { - return ::beman::execution::get_completion_signatures<::beman::execution::detail::child_type, Env...>(); + return ::beman::execution::get_completion_signatures<::beman::execution::detail::child_type, + ::beman::execution::detail::fwd_env_t...>(); } template <::beman::execution::sender Sender> diff --git a/include/beman/execution/detail/spawn.hpp b/include/beman/execution/detail/spawn.hpp index 0f54d91f..b85eaefd 100644 --- a/include/beman/execution/detail/spawn.hpp +++ b/include/beman/execution/detail/spawn.hpp @@ -20,6 +20,9 @@ import beman.execution.detail.queryable; import beman.execution.detail.receiver; import beman.execution.detail.scope_token; import beman.execution.detail.sender; +import beman.execution.detail.sender_in; +import beman.execution.detail.sends; +import beman.execution.detail.set_error; import beman.execution.detail.spawn_get_allocator; import beman.execution.detail.start; import beman.execution.detail.write_env; @@ -31,6 +34,9 @@ import beman.execution.detail.write_env; #include #include #include +#include +#include +#include #include #include #include @@ -92,6 +98,11 @@ struct spawn_t { auto [all, senv] = ::beman::execution::detail::spawn_get_allocator(new_sender, env); using sender_t = decltype(::beman::execution::write_env(::std::move(new_sender), senv)); + static_assert(::beman::execution::sender_in>); + static_assert( + !::beman::execution::detail::sends<::beman::execution::set_error_t, sender_t, ::beman::execution::env<>>, + "`the sender must either succeed or be canceled; it cannot fail!"); + using state_t = state; using alloc_t = typename ::std::allocator_traits::template rebind_alloc; using traits_t = ::std::allocator_traits; diff --git a/include/beman/execution/detail/starts_on.hpp b/include/beman/execution/detail/starts_on.hpp index a21e05da..0a7bc9c7 100644 --- a/include/beman/execution/detail/starts_on.hpp +++ b/include/beman/execution/detail/starts_on.hpp @@ -18,6 +18,7 @@ import beman.execution.detail.child_type; import beman.execution.detail.completion_signatures; import beman.execution.detail.completion_signatures_of_t; import beman.execution.detail.continues_on; +import beman.execution.detail.data_type; import beman.execution.detail.default_impls; import beman.execution.detail.dependent_sender; import beman.execution.detail.env; @@ -51,6 +52,7 @@ import beman.execution.detail.set_value; #include #include #include +#include #include #include #include @@ -98,34 +100,6 @@ struct starts_on_t { } private: - template - struct get_signatures; - template - requires(!::beman::execution::dependent_sender<::beman::execution::schedule_result_t>) - struct get_signatures< - ::beman::execution::detail::basic_sender<::beman::execution::detail::starts_on_t, Scheduler, Child>> - : get_signatures> {}; - template - requires requires { - starts_on_t::transform_sender( - ::beman::execution::set_value, - ::std::declval<::beman::execution::detail:: - basic_sender<::beman::execution::detail::starts_on_t, Scheduler, Child>>(), - ::std::declval()); - } - struct get_signatures< - ::beman::execution::detail::basic_sender<::beman::execution::detail::starts_on_t, Scheduler, Child>, - Env> { - static consteval auto get() { - using transformed_sndr = decltype(starts_on_t::transform_sender( - ::beman::execution::set_value, - ::std::declval<::beman::execution::detail:: - basic_sender<::beman::execution::detail::starts_on_t, Scheduler, Child>>(), - ::std::declval())); - return ::beman::execution::get_completion_signatures(); - } - }; - template struct attrs : ::beman::execution::detail::hide_completion_queries { using base = ::beman::execution::detail::hide_completion_queries; @@ -158,11 +132,17 @@ struct starts_on_t { Scheduler sch; }; + template + using transformed_sender = decltype(starts_on_t::transform_sender( + ::beman::execution::set_value, ::std::declval(), ::std::declval<::beman::execution::env<>>())); + public: - template - requires requires { get_signatures<::std::remove_cvref_t, Env...>{}; } + template <::beman::execution::sender Sender> + requires(!::beman::execution::dependent_sender< + ::beman::execution::schedule_result_t<::beman::execution::detail::data_type>>) && + ::beman::execution::sender_in> static consteval auto get_completion_signatures() { - return get_signatures<::std::remove_cvref_t, Env...>::get(); + return ::beman::execution::get_completion_signatures>(); } struct impls_for : ::beman::execution::detail::default_impls { diff --git a/include/beman/execution/detail/stopped_as_error.hpp b/include/beman/execution/detail/stopped_as_error.hpp index c5cf8b00..5614f57a 100644 --- a/include/beman/execution/detail/stopped_as_error.hpp +++ b/include/beman/execution/detail/stopped_as_error.hpp @@ -35,7 +35,7 @@ import beman.execution.detail.set_value; #endif namespace beman::execution::detail { -struct stopped_as_error_t : ::beman::execution::sender_adaptor_closure { +struct stopped_as_error_t { template <::beman::execution::detail::sender_for Sndr, typename Env> auto transform_sender(::beman::execution::set_value_t, Sndr&& sndr, Env&&) const noexcept { auto&& data = sndr.template get<1>(); diff --git a/include/beman/execution/detail/stopped_as_optional.hpp b/include/beman/execution/detail/stopped_as_optional.hpp index ab1ed114..21eb4f18 100644 --- a/include/beman/execution/detail/stopped_as_optional.hpp +++ b/include/beman/execution/detail/stopped_as_optional.hpp @@ -43,7 +43,7 @@ import beman.execution.detail.then; #endif namespace beman::execution::detail { -struct stopped_as_optional_t : ::beman::execution::sender_adaptor_closure { +struct stopped_as_optional_t { template <::beman::execution::detail::sender_for Sndr, typename Env> auto transform_sender(::beman::execution::set_value_t, Sndr&& sndr, Env&&) const noexcept { static_assert( diff --git a/include/beman/execution/detail/then.hpp b/include/beman/execution/detail/then.hpp index 2c6b99cb..7ebdf093 100644 --- a/include/beman/execution/detail/then.hpp +++ b/include/beman/execution/detail/then.hpp @@ -114,7 +114,7 @@ struct then_exception -struct then_t : ::beman::execution::sender_adaptor_closure> { +struct then_t { template <::beman::execution::detail::movable_value Fun> auto operator()(Fun&& fun) const noexcept(::std::is_nothrow_constructible_v<::std::remove_cvref_t, Fun>) { return ::beman::execution::detail::make_sender_adaptor(*this, std::forward(fun)); @@ -135,16 +135,15 @@ struct then_t : ::beman::execution::sender_adaptor_closure> { private: template struct get_signatures; - template - struct get_signatures : get_signatures> {}; - template - requires ::beman::execution::sender_in> + + template + requires ::beman::execution::sender_in...> struct get_signatures< ::beman::execution::detail::basic_sender<::beman::execution::detail::then_t, Fun, Child>, - Env> { + Env...> { static consteval auto get() { [[maybe_unused]] auto child_sigs = - ::beman::execution::get_completion_signatures>(); + ::beman::execution::get_completion_signatures...>(); using child_sigs_t = decltype(child_sigs); using type = ::beman::execution::detail::meta::unique<::beman::execution::detail::meta::combine< ::beman::execution::detail::meta::transform< diff --git a/include/beman/execution/detail/when_all_with_variant.hpp b/include/beman/execution/detail/when_all_with_variant.hpp index 56730760..65a9e9ed 100644 --- a/include/beman/execution/detail/when_all_with_variant.hpp +++ b/include/beman/execution/detail/when_all_with_variant.hpp @@ -54,7 +54,7 @@ import beman.execution.detail.when_all; namespace beman::execution::detail { struct when_all_with_variant_t { template <::beman::execution::detail::sender_for Sender, typename Env> - auto transform_sender(::beman::execution::set_value_t, Sender&& sender, const Env&) const noexcept { + static auto transform_sender(::beman::execution::set_value_t, Sender&& sender, const Env&) noexcept { return ::std::forward(sender).apply([](auto&&, auto&&, auto&&... child) { return ::beman::execution::when_all( ::beman::execution::into_variant(::beman::execution::detail::forward_like(child))...); @@ -67,23 +67,6 @@ struct when_all_with_variant_t { } private: - template - struct get_signatures; - template - struct get_signatures : get_signatures> {}; - template - requires(... && ::beman::execution::sender_in>) - struct get_signatures<::beman::execution::detail:: - basic_sender<::beman::execution::detail::when_all_with_variant_t, Data, Children...>, - Env> { - - static consteval auto get() { - using sndr_t = decltype(::beman::execution::when_all( - ::beman::execution::into_variant(::std::declval())...)); - return ::beman::execution::get_completion_signatures(); - } - }; - template struct attrs { template @@ -129,11 +112,15 @@ struct when_all_with_variant_t { } }; + template + using transformed_sender = decltype(when_all_with_variant_t::transform_sender( + ::beman::execution::set_value, ::std::declval(), ::std::declval<::beman::execution::env<>>())); + public: - template <::beman::execution::sender Sender, typename... Env> - requires requires { get_signatures<::std::remove_cvref_t, Env...>{}; } + template <::beman::execution::sender Sender> + requires ::beman::execution::sender_in> static consteval auto get_completion_signatures() { - return get_signatures<::std::remove_cvref_t, Env...>::get(); + return ::beman::execution::get_completion_signatures>(); } struct impls_for : ::beman::execution::detail::default_impls { diff --git a/tests/beman/execution/exec-run-loop-types.test.cpp b/tests/beman/execution/exec-run-loop-types.test.cpp index d0300df5..f3e47304 100644 --- a/tests/beman/execution/exec-run-loop-types.test.cpp +++ b/tests/beman/execution/exec-run-loop-types.test.cpp @@ -16,6 +16,7 @@ import beman.execution; #include #include #include +#include #include #include #include @@ -24,6 +25,7 @@ import beman.execution; #include #include #include +#include #endif // ---------------------------------------------------------------------------- @@ -139,5 +141,8 @@ TEST(exec_run_loop_types) { ASSERT(unstopped_result == signal_type::value); ASSERT(stopped_result == signal_type::stopped); + static_assert(test_std::dependent_sender); + static_assert(test_std::dependent_sender); + //-dk:TODO more thorough run_loop tests } diff --git a/tests/beman/execution/exec-snd-concepts.test.cpp b/tests/beman/execution/exec-snd-concepts.test.cpp index 27cd687d..54f21017 100644 --- a/tests/beman/execution/exec-snd-concepts.test.cpp +++ b/tests/beman/execution/exec-snd-concepts.test.cpp @@ -176,6 +176,19 @@ auto test_sender_in() -> void { static_assert(!test_std::sender_in); static_assert(test_std::sender_in); + + auto sndr3 = + test_std::read_env(test_std::get_allocator) | test_std::bulk(test_std::par, 1, [](int, auto&) noexcept {}); + static_assert(!test_std::sender_in>); + static_assert(test_std::sender_in); + + auto sndr4 = test_std::read_env(test_std::get_allocator) | test_std::continues_on(loop.get_scheduler()); + static_assert(!test_std::sender_in>); + static_assert(test_std::sender_in); + + auto sndr5 = test_std::starts_on(loop.get_scheduler(), test_std::read_env(test_std::get_allocator)); + static_assert(!test_std::sender_in>); + static_assert(test_std::sender_in); } auto test_tag_of_t() -> void { diff --git a/tests/beman/execution/exec-spawn.test.cpp b/tests/beman/execution/exec-spawn.test.cpp index aa354238..66b472e0 100644 --- a/tests/beman/execution/exec-spawn.test.cpp +++ b/tests/beman/execution/exec-spawn.test.cpp @@ -52,6 +52,12 @@ struct sender { }; base** handle{}; + + template + static consteval auto get_completion_signatures() noexcept -> completion_signatures { + return {}; + } + template auto connect(Rcvr&& rcvr) -> state { return state{std::forward(rcvr), *this->handle};