Skip to content

Instantly share code, notes, and snippets.

@yohhoy
Last active June 24, 2025 16:52
Show Gist options
  • Save yohhoy/305c704e2d60aafb8c541048cb70273a to your computer and use it in GitHub Desktop.
Save yohhoy/305c704e2d60aafb8c541048cb70273a to your computer and use it in GitHub Desktop.
Cancellable sender in C++26 S/R library
#include <cassert>
#include <stop_token>
#include <utility>
#include <print>
// https://github.com/NVIDIA/stdexec/
#include <stdexec/execution.hpp>
namespace exec = stdexec;
namespace std {
using exec::get_stop_token, exec::sync_wait;
}
template<typename Rcvr, typename F>
struct OpState {
using operation_state_concept = exec::operation_state_t;
void start() & noexcept {
auto st = std::get_stop_token(exec::get_env(rcvr_));
if (st. stop_requested()) {
exec::set_stopped(std::move(rcvr_));
std::println("set_stopped");
return;
}
try {
exec::set_value(std::move(rcvr_), f_());
std::println("set_value");
} catch (...) {
exec::set_error(std::move(rcvr_), std::current_exception());
std::println("set_error");
}
}
Rcvr rcvr_;
F f_;
};
template<typename F>
struct MySender {
using sender_concept = exec::sender_t;
using result_type = std::invoke_result_t<F>;
using completion_signatures = exec::completion_signatures<
exec::set_value_t(result_type),
exec::set_error_t(std::exception_ptr),
exec::set_stopped_t()
>;
template<typename Rcvr>
auto connect(Rcvr rcvr) {
return OpState{std::move(rcvr), std::move(f_)};
}
F f_;
};
template<typename F>
void invoke(F f)
{
exec::sender auto sndr = MySender{std::move(f)};
try {
auto [val] = std::sync_wait(sndr).value();
std::println("val={}", val);
} catch (int e) {
std::println("catch {}", e);
}
}
int main()
{
invoke([] -> int { return 1; });
std::println();
invoke([] -> int { throw 42; });
std::println();
exec::sender auto snd1 = MySender{[] -> int { return 1; }};
exec::sender auto snd2 = MySender{[] -> int { throw 42; }};
exec::sender auto snd3 = MySender{[] -> int { return 3; }};
exec::sender auto sndr = exec::when_all(snd1, snd2, snd3);
try {
auto tup = std::sync_wait(sndr).value();
std::println("val={}", tup);
} catch (int e) {
std::println("catch {}", e);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment