Skip to content

Instantly share code, notes, and snippets.

@dietmarkuehl
Created September 20, 2024 01:48
Show Gist options
  • Save dietmarkuehl/053ec13b84732670ea8739cbaa51421a to your computer and use it in GitHub Desktop.
Save dietmarkuehl/053ec13b84732670ea8739cbaa51421a to your computer and use it in GitHub Desktop.
example of using stop tokens
// examples/client.cpp -*-C++-*-
// ----------------------------------------------------------------------------
//
// Copyright (c) 2024 Dietmar Kuehl http://www.dietmar-kuehl.de
//
// Licensed under the Apache License Version 2.0 with LLVM Exceptions
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// https://llvm.org/LICENSE.txt
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// ----------------------------------------------------------------------------
#include <stdexec/execution.hpp>
#include <chrono>
#include <iostream>
#include <thread>
using namespace std::chrono;
namespace ex = stdexec;
// ----------------------------------------------------------------------------
template <typename> struct say_it;
template <typename T>
auto say_signature(T&& t) {
return say_it<decltype(ex::get_completion_signatures(t, ex::empty_env{}))>{};
}
template <typename Sender>
struct inject_cancel_sender
{
using sender_concept = ex::sender_t;
struct env
{
ex::inplace_stop_token token{};
auto query(ex::get_stop_token_t) const noexcept {
std::cout << "query(stop_token)\n";
return this->token;
}
};
template <typename Receiver>
struct receiver
{
using receiver_concept = ex::receiver_t;
std::remove_cvref_t<Receiver> inner_receiver;
ex::inplace_stop_token token{};
auto get_env() const noexcept -> env {
std::cout << "get_env\n";
return {this->token};
}
template <typename... T>
auto set_value(T&&... t) noexcept -> void {
ex::set_value(std::move(inner_receiver), std::forward<T>(t)...);
}
template <typename E>
auto set_error(E&& e) noexcept -> void {
ex::set_error(std::move(inner_receiver), std::forward<E>(e));
}
auto set_stopped() noexcept -> void {
ex::set_stopped(std::move(inner_receiver));
}
};
template <typename E>
auto get_completion_signatures(E const& e) {
return ex::get_completion_signatures(this->sender, e);
}
ex::inplace_stop_token token{};
Sender sender;
template <typename Receiver>
auto connect(Receiver&& recv) && {
return ex::connect(std::move(sender), receiver<Receiver>(std::forward<Receiver>(recv)));
}
};
template <typename S>
inject_cancel_sender(ex::inplace_stop_token, S&&) -> inject_cancel_sender<std::decay_t<S>>;
struct receiver
{
using receiver_concept = ex::receiver_t;
auto set_value(auto&&...) noexcept -> void {}
auto set_error(auto&&) noexcept -> void {}
auto set_stopped() noexcept -> void {}
};
int main()
{
ex::inplace_stop_source source;
#if 1
std::thread t([token=source.get_token()]{
ex::sync_wait(
inject_cancel_sender{token,
ex::let_value(
ex::read_env(ex::get_stop_token),
[](auto token){
say_it<decltype(token)>{};
while (!token.stop_requested())
{
std::cout << "sleeping\n" << std::flush;
std::this_thread::sleep_for(1s);
}
std::cout << "stopped\n";
return ex::just(0);
})
}
);
}
);
int i{};
std::cin >> i;
std::cout << "requesting stop\n";
source.request_stop();
t.join();
#else
say_signature(ex::read_env(ex::get_stop_token))
say_signature(ex::just(source.get_token()));
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment