Skip to content

Commit 2cb0bd8

Browse files
committed
convert awaiter to sender
1 parent ed49b71 commit 2cb0bd8

2 files changed

Lines changed: 75 additions & 0 deletions

File tree

‎include/condy/execution.hpp‎

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22

3+
#include "condy/concepts.hpp"
34
#include "condy/runtime.hpp"
45
#include <stdexec/execution.hpp>
56

@@ -40,6 +41,57 @@ class ScheduleSender {
4041
Runtime &runtime_;
4142
};
4243

44+
template <AwaiterLike Awaiter> class AwaiterSender {
45+
public:
46+
using sender_concept = stdexec::sender_t;
47+
48+
using completion_signatures = stdexec::completion_signatures<
49+
stdexec::set_value_t(typename Awaiter::HandleType::ReturnType),
50+
stdexec::set_error_t(std::exception_ptr)>;
51+
52+
AwaiterSender(Awaiter awaiter) : awaiter_(std::move(awaiter)) {}
53+
54+
template <typename Receiver> auto connect(Receiver &&receiver) {
55+
return OpState<std::decay_t<Receiver>>(
56+
std::move(awaiter_), std::forward<Receiver>(receiver));
57+
}
58+
59+
private:
60+
template <typename Receiver>
61+
class OpState : public InvokerAdapter<OpState<Receiver>> {
62+
public:
63+
OpState(Awaiter awaiter, Receiver receiver)
64+
: awaiter_(std::move(awaiter)), receiver_(std::move(receiver)) {}
65+
66+
void start() noexcept {
67+
awaiter_.init_finish_handle();
68+
awaiter_.get_handle()->set_invoker(this);
69+
awaiter_.register_operation(0);
70+
}
71+
72+
void invoke() noexcept {
73+
try {
74+
auto result = awaiter_.await_resume();
75+
stdexec::set_value(std::move(receiver_), std::move(result));
76+
} catch (...) {
77+
stdexec::set_error(std::move(receiver_),
78+
std::current_exception());
79+
}
80+
}
81+
82+
private:
83+
Awaiter awaiter_;
84+
Receiver receiver_;
85+
};
86+
;
87+
88+
Awaiter awaiter_;
89+
};
90+
91+
template <AwaiterLike Awaiter> auto convert_to_sender(Awaiter &&awaiter) {
92+
return AwaiterSender<std::decay_t<Awaiter>>(std::forward<Awaiter>(awaiter));
93+
}
94+
4395
} // namespace detail
4496

4597
class RuntimeScheduler {

‎tests/test_execution.cpp‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include "condy/async_operations.hpp"
12
#include "condy/execution.hpp"
23
#include "condy/runtime.hpp"
34
#include <doctest/doctest.h>
@@ -24,6 +25,28 @@ TEST_CASE("test execution - schedule") {
2425
REQUIRE(thread_id == runtime_thread_id);
2526
REQUIRE(runtime_thread_id != std::this_thread::get_id());
2627

28+
runtime.allow_exit();
29+
runtime_thread.join();
30+
}
31+
32+
TEST_CASE("test execution - awaiter") {
33+
condy::Runtime runtime;
34+
std::thread runtime_thread([&] { runtime.run(); });
35+
36+
bool executed = false;
37+
auto scheduler = condy::RuntimeScheduler(runtime);
38+
auto nop_awaiter = condy::async_nop();
39+
auto nop_sender = condy::detail::convert_to_sender(nop_awaiter);
40+
auto sender = stdexec::schedule(scheduler) |
41+
stdexec::let_value([&]() { return nop_sender; }) |
42+
stdexec::then([&](auto res) {
43+
REQUIRE(res == 0);
44+
executed = true;
45+
});
46+
47+
stdexec::sync_wait(sender);
48+
REQUIRE(executed);
49+
2750
runtime.allow_exit();
2851
runtime_thread.join();
2952
}

0 commit comments

Comments
 (0)