Let future-operation be the exposition-only class template:
namespace std::execution {
template<class StatePtr, class Rcvr>
struct future-operation {
struct callback {
try-cancelable* state;
void operator()() noexcept {
state->try-cancel();
};
};
using stop-token-t =
stop_token_of_t<env_of_t<Rcvr>>;
using stop-callback-t =
stop_callback_for_t<stop-token-t, callback>;
struct rcvr-t {
using receiver_concept = receiver_tag;
future-operation* op;
template<class... T>
void set_value(T&&... ts) && noexcept {
op->set-complete<set_value_t>(std::forward<T>(ts)...);
}
template<class E>
void set_error(E&& e) && noexcept {
op->set-complete<set_error_t>(std::forward<E>(e));
}
void set_stopped() && noexcept {
op->set-complete<set_stopped_t>();
}
env_of_t<Rcvr> get_env() const noexcept {
return execution::get_env(op->rcvr);
}
};
Rcvr rcvr;
StatePtr state;
rcvr-t inner;
optional<stop-callback-t> stopCallback;
future-operation(StatePtr state, Rcvr rcvr) noexcept
: rcvr(std::move(rcvr)), state(std::move(state)), inner(this)
{}
future-operation(future-operation&&) = delete;
void run() & noexcept {
constexpr bool nothrow =
is_nothrow_constructible_v<stop-callback-t, stop-token-t, callback>;
try {
stopCallback.emplace(get_stop_token(rcvr), callback(state.get()));
}
catch (...) {
if constexpr (!nothrow) {
set_error(std::move(rcvr), current_exception());
return;
}
}
state.release()->consume(inner);
}
template<class CPO, class... T>
void set-complete(T&&... ts) noexcept {
stopCallback.reset();
CPO{}(std::move(rcvr), std::forward<T>(ts)...);
}
};
}