1#ifndef KOKKOS_EXECUTION_EXECUTION_SPACE_OPERATION_STATE_HPP
2#define KOKKOS_EXECUTION_EXECUTION_SPACE_OPERATION_STATE_HPP
15template <
typename Clsr>
16concept Closure =
requires(
const Clsr& clsr) {
17 typename Clsr::execution_space;
19 { clsr.execute() } -> std::same_as<void>;
21 { clsr.get_policy() };
22 requires Kokkos::ExecutionPolicy<std::remove_cvref_t<
decltype(clsr.get_policy())>>;
24 requires std::same_as<std::remove_cvref_t<
decltype(clsr.get_policy().space())>,
typename Clsr::execution_space>;
35template <stdexec::receiver Rcvr,
typename OpState>
38 || stdexec::__is_instance_of<Rcvr, SyncWaitReceiver>;
55 std::remove_cvref_t<stdexec::__query_result_t<stdexec::env_of_t<Rcvr>,
get_exec_t>>,
56 stdexec::__query_result_t<OpState, get_exec_t>
58 return opstate.query(
get_exec).get() !=
get_exec(stdexec::get_env(opstate.rcvr)).get();
72template <
typename Rcvr,
typename Exec>
75 && stdexec::__queryable_with<stdexec::env_of_t<Rcvr>, stdexec::get_delegation_scheduler_t>;
78 stdexec::receiver Rcvr,
79 Kokkos::ExecutionSpace Exec,
84template <stdexec::receiver Rcvr, Kokkos::ExecutionSpace Exec>
96 stdexec::set_value(std::move(
opstate->rcvr));
99 stdexec::set_error(std::move(
opstate->rcvr), std::current_exception());
104template <stdexec::receiver Rcvr, Kokkos::ExecutionSpace Exec>
110 template <
typename OpState>
115 stdexec::set_value(std::move(this->rcvr));
119template <stdexec::receiver Rcvr, Kokkos::ExecutionSpace Exec>
123 stdexec::schedule_result_t<
124 stdexec::__query_result_t<stdexec::env_of_t<Rcvr>, stdexec::get_delegation_scheduler_t>
130 stdexec::__manual_lifetime<opstate_t>
storage{};
132 template <
typename OpState>
137 stdexec::schedule(stdexec::get_delegation_scheduler(stdexec::get_env(this->rcvr))),
139 stdexec::start(
storage.__get());
141 stdexec::set_value(std::move(this->rcvr));
146template <stdexec::receiver Rcvr, Closure Clsr, Closure... Clsrs>
147requires(std::same_as<typename Clsr::execution_space, typename Clsrs::execution_space> && ...)
159 constexpr explicit OpStateBase(Rcvr rcvr_, Clsr clsr_, Clsrs... clsrs_)
noexcept(
160 std::is_nothrow_constructible_v<may_delegate_completion_with_event_t, Rcvr>
161 && std::is_nothrow_move_constructible_v<Clsr> && (std::is_nothrow_move_constructible_v<Clsrs> && ...))
163 , clsrs(std::move(clsr_), std::move(clsrs_)...) {
168 stdexec::__apply([](
auto&... clsr) { (clsr.execute(), ...); },
clsrs);
174 may_delegate_completion_with_event_t::delegate(
this);
177 template <
typename Error>
179 stdexec::set_error(std::move(this->rcvr), std::forward<Error>(error));
183 stdexec::set_stopped(std::move(this->rcvr));
195template <
typename ParentOp>
202 parent_op->propagate_completion_signal(stdexec::set_value);
205 template <
typename Error>
207 parent_op->propagate_completion_signal(stdexec::set_error, std::forward<Error>(error));
211 parent_op->propagate_completion_signal(stdexec::set_stopped);
215 typename ParentOp::execution_space,
217 typename ParentOp::receiver_t,
221template <stdexec::sender Sndr, stdexec::receiver Rcvr,
Closure... Clsrs>
231 std::is_nothrow_constructible_v<
base_t, Rcvr&&, Clsrs&&...>;
234 stdexec::__nothrow_connectable<Sndr&&, OpStateReceiver<base_t>>;
242 :
base_t(std::move(rcvr_), std::move(clsrs_)...)
251template <
typename Sndr,
typename Rcvr,
typename... Clsrs>
256 constexpr auto operator()(Sndr&& sndr, Rcvr rcvr, Clsrs... clsrs)
const
257 noexcept(std::is_nothrow_constructible_v<
type, Sndr&&, Rcvr&&, Clsrs&&...>) ->
type {
258 return type(std::forward<Sndr>(sndr), std::move(rcvr), std::move(clsrs)...);
265 using clsr_of_sndr_t =
typename stdexec::transform_sender_result_t<Sndr, stdexec::env_of_t<Rcvr>>::closure_t;
272 stdexec::set_value_t,
274 stdexec::env_of_t<Rcvr>
287 constexpr auto operator()(Sndr&& sndr, Rcvr&& rcvr, Clsrs... clsrs)
const
289 auto trnsfrmd_sndr = stdexec::transform_sender(std::forward<Sndr>(sndr), stdexec::get_env(rcvr));
291 stdexec::__forward_like<Sndr>(trnsfrmd_sndr.sndr),
292 std::forward<Rcvr>(rcvr),
293 std::move(trnsfrmd_sndr.clsr),
294 std::move(clsrs)...);
298template <
typename Sndr,
typename Rcvr,
typename... Clsrs>
The execution space supports events and the receiver is queryable for a delegation scheduler.
Concept that constrains the type of a sender that dispatches a functor for execution.
#define KOKKOS_EXECUTION_FORWARDING_GET_ENV(_type_, _obj_)
Retrieve the environment of _obj_ (with forwarding). // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)...
#define KOKKOS_EXECUTION_UPSERT_EXEC(_exec_type_, _exec_, _rcvr_type_, _rcvr_)
typename MakeOpStateFn< Sndr, Rcvr, Clsrs... >::type opstate_t
constexpr get_exec_t get_exec
consteval std::string_view dispatch_label() noexcept
View the dispatch label as a std::string_view.
Wrap a Kokkos execution space to make it cheap to copy/move in new environments.
stdexec::__child_of< Sndr > child_of_sndr_t
static constexpr bool sndr_has_nothrow_transform_sender
typename stdexec::transform_sender_result_t< Sndr, stdexec::env_of_t< Rcvr > >::closure_t clsr_of_sndr_t
constexpr auto operator()(Sndr &&sndr, Rcvr &&rcvr, Clsrs... clsrs) const noexcept(sndr_has_nothrow_transform_sender &&is_nothrow_make_opstate) -> type
static constexpr bool is_nothrow_make_opstate
MakeOpStateFn< child_of_sndr_t, Rcvr, clsr_of_sndr_t, Clsrs... > make_opstate_fn_t
typename make_opstate_fn_t::type type
OpState< Sndr, Rcvr, Clsrs... > type
constexpr auto operator()(Sndr &&sndr, Rcvr rcvr, Clsrs... clsrs) const noexcept(std::is_nothrow_constructible_v< type, Sndr &&, Rcvr &&, Clsrs &&... >) -> type
void delegate(OpState *const opstate) noexcept
static constexpr auto label
void delegate(OpState *const opstate) noexcept
WaitEventReceiver< Rcvr, Exec > receiver_t
stdexec::__manual_lifetime< opstate_t > storage
stdexec::connect_result_t< stdexec::schedule_result_t< stdexec::__query_result_t< stdexec::env_of_t< Rcvr >, stdexec::get_delegation_scheduler_t > >, receiver_t > opstate_t
typename Clsr::execution_space execution_space
constexpr OpStateBase(Rcvr rcvr_, Clsr clsr_, Clsrs... clsrs_) noexcept(std::is_nothrow_constructible_v< may_delegate_completion_with_event_t, Rcvr > &&std::is_nothrow_move_constructible_v< Clsr > &&(std::is_nothrow_move_constructible_v< Clsrs > &&...))
void propagate_completion_signal(stdexec::set_error_t, Error &&error) noexcept
stdexec::__tuple< Clsr, Clsrs... > closures_t
MayDelegateCompletionWithEvent< Rcvr, execution_space > may_delegate_completion_with_event_t
constexpr auto query(get_exec_t) const noexcept -> ExecutionSpaceRef< execution_space >
void propagate_completion_signal(stdexec::set_value_t) noexcept
void propagate_completion_signal(stdexec::set_stopped_t) noexcept
void set_value() &&noexcept
stdexec::receiver_t receiver_concept
void set_error(Error &&error) &&noexcept
void set_stopped() &&noexcept
stdexec::connect_result_t< Sndr, OpStateReceiver< base_t > > inner_opstate_t
stdexec::operation_state_t operation_state_concept
constexpr OpState(Sndr &&sndr, Rcvr rcvr_, Clsrs... clsrs_) noexcept(opstate_base_is_nothrow_constructible &&inner_opstate_is_nothrow_constructible)
inner_opstate_t inner_opstate
OpStateBase< Rcvr, Clsrs... > base_t
static constexpr bool opstate_base_is_nothrow_constructible
static constexpr bool inner_opstate_is_nothrow_constructible
Synchronization at the boundary of the work enqueued on an execution space.
bool operator()(const OpState &opstate) const noexcept
static constexpr bool successor_handles_sync
constexpr bool operator()(const OpState &) const noexcept
The synchronization will be handled by the successor.
constexpr bool operator()(const OpState &) const noexcept
As a fallback, synchronization is always required.
Impl::Event< Exec > event_t
stdexec::receiver_t receiver_concept
void set_value() &&noexcept
MayDelegateCompletionWithEvent< Rcvr, Exec > * opstate
An event that can be recorded on an execution space instance.