Last active
June 24, 2025 16:52
-
-
Save yohhoy/305c704e2d60aafb8c541048cb70273a to your computer and use it in GitHub Desktop.
Cancellable sender in C++26 S/R library
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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