Skip to content

Commit 130f3bf

Browse files
committed
non working stop
1 parent aa35e4a commit 130f3bf

File tree

13 files changed

+425
-182
lines changed

13 files changed

+425
-182
lines changed

CMakeLists.txt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,28 @@ target_sources (
2727
src/io/addr.hxx
2828
src/io/addr.cxx
2929
src/io/endian.hxx
30-
src/io/polled_io.hxx
30+
src/io/polled_fd.hxx
3131
src/io/reactor.hxx
3232
src/io/reactor.cxx
3333
src/io/io_env.hxx
3434
src/io/context.hxx
3535
src/co/scheduler.hxx
3636
src/co/coroutine.hxx
3737
src/co/task.hxx
38+
src/co/received.hxx
3839
src/fastipc.cxx
3940
src/visitor.hxx
4041
src/channel.hxx
4142
)
43+
4244
if (NOT DEFINED CMAKE_CXX_CLANG_TIDY OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
4345
target_precompile_headers (fastipc PUBLIC include/fastipc.hxx)
4446
endif ()
4547

46-
target_compile_features (fastipc INTERFACE cxx_std_17)
48+
target_compile_features (fastipc INTERFACE cxx_std_23)
4749
target_compile_features (fastipc PRIVATE cxx_std_23)
4850
target_compile_options (fastipc PRIVATE ${FASTIPC_COMPILE_OPTIONS} -Wno-zero-length-array)
51+
target_include_directories (fastipc PUBLIC src)
4952

5053
add_library (tower OBJECT)
5154
target_include_directories (tower PUBLIC src)
@@ -57,7 +60,7 @@ target_link_libraries (tower PRIVATE fastipc)
5760
add_executable (fastipcd)
5861
target_sources (fastipcd PRIVATE src/main.cxx)
5962
target_compile_options (fastipcd PRIVATE ${FASTIPC_COMPILE_OPTIONS})
60-
target_link_libraries (fastipcd PRIVATE tower)
63+
target_link_libraries (fastipcd PRIVATE tower fastipc)
6164

6265
enable_testing ()
6366
add_subdirectory (test)

src/co/coroutine.hxx

Lines changed: 147 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,66 @@
2222
#include <cassert>
2323
#include <coroutine>
2424
#include <exception>
25-
#include <memory>
2625
#include <print>
26+
#include <stop_token>
2727
#include <type_traits>
2828
#include <utility>
29-
#include <variant>
3029
#include "received.hxx"
31-
#include "visitor.hxx"
3230

3331
namespace fastipc::co {
3432

33+
template <class T>
34+
class Receiver {
35+
public:
36+
Receiver() = default;
37+
38+
Receiver(Receiver&&) noexcept = default;
39+
Receiver& operator=(Receiver&&) noexcept = default;
40+
41+
Receiver(const Receiver&) noexcept = default;
42+
Receiver& operator=(const Receiver&) noexcept = default;
43+
44+
virtual ~Receiver() = default;
45+
46+
virtual void set_value(T value) noexcept = 0;
47+
virtual void set_exception(std::exception_ptr error) noexcept = 0;
48+
virtual void set_stopped() noexcept = 0;
49+
};
50+
51+
template <>
52+
class Receiver<void> {
53+
public:
54+
Receiver() = default;
55+
56+
Receiver(Receiver&&) noexcept = default;
57+
Receiver& operator=(Receiver&&) noexcept = default;
58+
59+
Receiver(const Receiver&) noexcept = default;
60+
Receiver& operator=(const Receiver&) noexcept = default;
61+
62+
virtual ~Receiver() = default;
63+
64+
virtual void set_value() noexcept = 0;
65+
virtual void set_exception(std::exception_ptr error) noexcept = 0;
66+
virtual void set_stopped() noexcept = 0;
67+
};
68+
69+
class Handler {
70+
public:
71+
Handler() = default;
72+
73+
Handler(Handler&&) noexcept = delete;
74+
Handler& operator=(Handler&&) noexcept = delete;
75+
76+
Handler(const Handler&) noexcept = delete;
77+
Handler& operator=(const Handler&) noexcept = delete;
78+
79+
virtual ~Handler() = default;
80+
81+
virtual void unhandled_exception() noexcept = 0;
82+
virtual void unhandled_stopped() noexcept = 0;
83+
};
84+
3585
template <class T>
3686
concept valueless = std::is_void_v<T>;
3787

@@ -45,7 +95,7 @@ template <class T, class Env>
4595
class Task;
4696

4797
template <class Env>
48-
class EnvAwaiter final {
98+
class EnvAwaiter {
4999
public:
50100
bool await_ready() noexcept { return false; }
51101

@@ -62,12 +112,12 @@ class EnvAwaiter final {
62112
const Env* m_env = nullptr;
63113
};
64114

65-
struct GetEnv final {};
115+
struct GetEnv {};
66116

67117
constexpr GetEnv getEnv() noexcept { return {}; }
68118

69119
template <class T, class Env>
70-
class [[nodiscard]] Co final {
120+
class [[nodiscard]] Co {
71121
public:
72122
using promise_type = Promise<T, Env>;
73123
using handle_type = std::coroutine_handle<promise_type>;
@@ -104,63 +154,25 @@ class [[nodiscard]] Co final {
104154
handle_type m_handle;
105155
};
106156

107-
template <class T>
108-
class Receiver {
109-
public:
110-
Receiver() = default;
111-
112-
Receiver(Receiver&&) noexcept = default;
113-
Receiver& operator=(Receiver&&) noexcept = default;
114-
115-
Receiver(const Receiver&) noexcept = default;
116-
Receiver& operator=(const Receiver&) noexcept = default;
117-
118-
virtual ~Receiver() = default;
119-
120-
virtual void set_value(T value) noexcept = 0;
121-
virtual void set_exception(std::exception_ptr error) noexcept = 0;
122-
};
123-
124-
template <>
125-
class Receiver<void> {
126-
public:
127-
Receiver() = default;
128-
129-
Receiver(Receiver&&) noexcept = default;
130-
Receiver& operator=(Receiver&&) noexcept = default;
131-
132-
Receiver(const Receiver&) noexcept = default;
133-
Receiver& operator=(const Receiver&) noexcept = default;
134-
135-
virtual ~Receiver() = default;
136-
137-
virtual void set_value() noexcept = 0;
138-
virtual void set_exception(std::exception_ptr error) noexcept = 0;
139-
};
140-
141157
template <class T, class Env>
142-
class FinalAwaiter final {
158+
class FinalAwaiter {
143159
public:
144160
bool await_ready() noexcept { return false; }
145161

146162
std::coroutine_handle<> await_suspend(std::coroutine_handle<Promise<T, Env>> completed) {
147163
assert(completed.promise().m_received.has_value());
148164
auto& promise = completed.promise();
149165

150-
return match(
151-
std::move(promise.m_cont), [](std::coroutine_handle<> cont) -> std::coroutine_handle<> { return cont; },
152-
[&promise](std::shared_ptr<Receiver<T>> receiver) -> std::coroutine_handle<> {
153-
std::move(promise.m_received).forward(*receiver);
166+
std::move(promise.m_received).forward(*promise.m_cont);
154167

155-
return std::noop_coroutine();
156-
});
168+
return std::noop_coroutine();
157169
}
158170

159171
void await_resume() noexcept {}
160172
};
161173

162174
template <class T, class Env>
163-
class Promise final {
175+
class Promise : public Handler {
164176
public:
165177
Promise() = default;
166178

@@ -170,7 +182,7 @@ class Promise final {
170182
Promise(const Promise&) noexcept = delete;
171183
Promise& operator=(const Promise&) noexcept = delete;
172184

173-
~Promise() noexcept = default;
185+
~Promise() noexcept override = default;
174186

175187
Co<T, Env> get_return_object() { return Co<T, Env>{std::coroutine_handle<Promise>::from_promise(*this)}; }
176188

@@ -182,7 +194,8 @@ class Promise final {
182194
}
183195

184196
void return_value(T value) noexcept { m_received.set_value(std::move(value)); }
185-
void unhandled_exception() noexcept { m_received.set_exception(std::current_exception()); }
197+
void unhandled_exception() noexcept override { m_received.set_exception(std::current_exception()); }
198+
void unhandled_stopped() noexcept override { m_received.set_stopped(); }
186199

187200
template <class A>
188201
decltype(auto) await_transform(A&& awaitable) noexcept {
@@ -192,6 +205,7 @@ class Promise final {
192205
EnvAwaiter<Env> await_transform(GetEnv) { return EnvAwaiter<Env>{}; }
193206

194207
const Env& env() const { return *m_env; }
208+
std::stop_token stop_token() { return m_env->stop_token; }
195209

196210
private:
197211
friend class Co<T, Env>;
@@ -201,13 +215,13 @@ class Promise final {
201215

202216
Received<T> m_received;
203217

204-
std::variant<std::coroutine_handle<>, std::shared_ptr<Receiver<T>>> m_cont = std::noop_coroutine();
218+
Receiver<T>* m_cont = nullptr;
205219

206220
const Env* m_env;
207221
};
208222

209223
template <class Env>
210-
class Promise<void, Env> final {
224+
class Promise<void, Env> : public Handler {
211225
public:
212226
Promise() = default;
213227

@@ -217,7 +231,7 @@ class Promise<void, Env> final {
217231
Promise(const Promise&) noexcept = delete;
218232
Promise& operator=(const Promise&) noexcept = delete;
219233

220-
~Promise() noexcept = default;
234+
~Promise() noexcept override = default;
221235

222236
Co<void, Env> get_return_object() { return Co<void, Env>{std::coroutine_handle<Promise>::from_promise(*this)}; }
223237

@@ -229,8 +243,8 @@ class Promise<void, Env> final {
229243
}
230244

231245
void return_void() noexcept { m_received.set_value(); }
232-
233-
void unhandled_exception() noexcept { m_received.set_exception(std::current_exception()); }
246+
void unhandled_exception() noexcept override { m_received.set_exception(std::current_exception()); }
247+
void unhandled_stopped() noexcept override { m_received.set_stopped(); }
234248

235249
template <class A>
236250
decltype(auto) await_transform(A&& awaitable) noexcept {
@@ -240,6 +254,7 @@ class Promise<void, Env> final {
240254
EnvAwaiter<Env> await_transform(GetEnv) { return EnvAwaiter<Env>{}; }
241255

242256
const Env& env() const { return *m_env; }
257+
std::stop_token stop_token() { return m_env->stop_token; }
243258

244259
private:
245260
friend class Co<void, Env>;
@@ -248,13 +263,78 @@ class Promise<void, Env> final {
248263
friend class Task<void, Env>;
249264

250265
Received<void> m_received;
251-
std::variant<std::coroutine_handle<>, std::shared_ptr<Receiver<void>>> m_cont = std::noop_coroutine();
266+
Receiver<void>* m_cont = nullptr;
267+
268+
const Env* m_env;
269+
};
270+
271+
template <class T, class Env>
272+
class CoReceiver : public Receiver<T> {
273+
public:
274+
CoReceiver() : Receiver<T>{} {}
275+
CoReceiver(std::coroutine_handle<> cont, const Env* env) : m_cont{cont}, m_env{env} {}
276+
277+
void set_value(T value) noexcept override {
278+
m_received.set_value(std::move(value));
279+
280+
m_env->scheduler->schedule([cont = m_cont]() { cont.resume(); });
281+
};
252282

283+
void set_exception(std::exception_ptr error) noexcept override {
284+
m_received.set_exception(error);
285+
286+
m_env->scheduler->schedule([cont = m_cont]() { cont.resume(); });
287+
};
288+
289+
// these also need to be scheduled...
290+
void set_stopped() noexcept override { m_received.set_stopped(); };
291+
292+
T resume() {
293+
assert(m_received.has_value());
294+
295+
return std::move(m_received).consume();
296+
}
297+
298+
private:
299+
Received<T> m_received;
300+
std::coroutine_handle<> m_cont;
301+
const Env* m_env;
302+
};
303+
304+
template <class Env>
305+
class CoReceiver<void, Env> : public Receiver<void> {
306+
public:
307+
CoReceiver() : Receiver<void>{} {}
308+
CoReceiver(std::coroutine_handle<> cont, const Env* env) : m_cont{cont}, m_env{env} {}
309+
310+
void set_value() noexcept override {
311+
m_received.set_value();
312+
313+
m_env->scheduler->schedule([cont = m_cont]() { cont.resume(); });
314+
};
315+
316+
void set_exception(std::exception_ptr error) noexcept override {
317+
m_received.set_exception(error);
318+
319+
m_env->scheduler->schedule([cont = m_cont]() { cont.resume(); });
320+
};
321+
322+
// these also need to be scheduled...
323+
void set_stopped() noexcept override { m_received.set_stopped(); };
324+
325+
void resume() {
326+
assert(m_received.has_value());
327+
std::move(m_received).consume();
328+
}
329+
330+
private:
331+
Received<void> m_received;
332+
std::coroutine_handle<> m_cont;
253333
const Env* m_env;
254334
};
255335

256336
template <class T, class Env>
257-
class [[nodiscard]] CoAwaiter final {
337+
class [[nodiscard]] CoAwaiter {
258338
public:
259339
explicit CoAwaiter(Co<T, Env> co) noexcept : m_co{std::move(co)} {}
260340

@@ -270,23 +350,26 @@ class [[nodiscard]] CoAwaiter final {
270350

271351
template <class S>
272352
std::coroutine_handle<> await_suspend(std::coroutine_handle<Promise<S, Env>> cont) {
273-
m_co.m_handle.promise().m_env = &cont.promise().env();
274-
m_co.m_handle.promise().m_cont = cont;
353+
const auto env = &cont.promise().env();
275354

355+
m_co.env(env);
356+
357+
m_receiver = {cont, env};
358+
m_co.m_handle.promise().m_cont = &m_receiver;
359+
360+
// TODO: move to scheduler
276361
return m_co.m_handle;
277362
}
278363

279364
T await_resume() {
280-
auto co = std::move(m_co);
281-
282-
auto& promise = co.m_handle.promise();
365+
auto _ = std::move(m_co);
283366

284-
assert(promise.m_received.has_value());
285-
return std::move(promise.m_received).consume();
367+
return m_receiver.resume();
286368
}
287369

288370
private:
289371
Co<T, Env> m_co;
372+
CoReceiver<T, Env> m_receiver;
290373
};
291374

292375
template <class T, class Env>

0 commit comments

Comments
 (0)