summaryrefslogtreecommitdiff
path: root/aisa/coroutine.h
diff options
context:
space:
mode:
Diffstat (limited to 'aisa/coroutine.h')
-rw-r--r--aisa/coroutine.h119
1 files changed, 0 insertions, 119 deletions
diff --git a/aisa/coroutine.h b/aisa/coroutine.h
deleted file mode 100644
index 1b55362..0000000
--- a/aisa/coroutine.h
+++ /dev/null
@@ -1,119 +0,0 @@
1#pragma once
2
3#include <coroutine>
4#include <optional>
5
6namespace aisa {
7
8 template<typename result_t> struct task_promise;
9
10 template<typename result_t> struct task : public std::coroutine_handle<task_promise<result_t>> {
11 using handle = std::coroutine_handle<task_promise<result_t>>;
12 using promise_type = task_promise<result_t>;
13 bool await_ready() const noexcept { return handle::done(); }
14 result_t await_resume() const noexcept;
15 template<typename other_t> void await_suspend(std::coroutine_handle<task_promise<other_t>> h) const noexcept;
16 std::optional<result_t> operator()() noexcept;
17 };
18
19 template<> struct task<void> : public std::coroutine_handle<task_promise<void>> {
20 using handle = std::coroutine_handle<task_promise<void>>;
21 using promise_type = task_promise<void>;
22 bool await_ready() const noexcept { return handle::done(); }
23 void await_resume() const noexcept;
24 template<typename other_t> void await_suspend(std::coroutine_handle<task_promise<other_t>> h) const noexcept;
25 bool operator()() noexcept;
26 };
27
28 template<typename result_t> struct task_promise {
29 std::coroutine_handle<> precursor;
30 std::optional<result_t> result;
31 task_promise() = default;
32 task_promise(const task_promise &) = delete;
33 task<result_t> get_return_object() noexcept { return task<result_t>{std::coroutine_handle<task_promise<result_t>>::from_promise(*this)}; }
34 std::suspend_never initial_suspend() const noexcept { return {}; }
35 std::suspend_always final_suspend() const noexcept { return {}; }
36 void unhandled_exception() { }
37 void return_value(result_t x) noexcept { result = std::move(x); }
38 };
39
40 template<> struct task_promise<void> {
41 std::coroutine_handle<> precursor;
42 task_promise() = default;
43 task_promise(const task_promise &) = delete;
44 task<void> get_return_object() noexcept { return task<void>{std::coroutine_handle<task_promise<void>>::from_promise(*this)}; }
45 std::suspend_never initial_suspend() const noexcept { return {}; }
46 std::suspend_always final_suspend() const noexcept { return {}; }
47 void unhandled_exception() { }
48 void return_void() noexcept { }
49 };
50
51 template<typename result_t> result_t task<result_t>::await_resume() const noexcept
52 {
53 auto x = std::move(handle::promise().result.value());
54 handle::destroy();
55 return x;
56 }
57
58 template<typename result_t> template<typename other_t> void task<result_t>::await_suspend(std::coroutine_handle<task_promise<other_t>> h) const noexcept
59 {
60 h.promise().precursor = *this;
61 }
62
63 template<typename result_t> std::optional<result_t> task<result_t>::operator()() noexcept
64 {
65 if (!handle::operator bool())
66 return {};
67 if (!handle::done()) {
68 auto &precursor = handle::promise().precursor;
69 if (precursor) {
70 if (!precursor.done())
71 precursor.resume();
72 if (precursor.done())
73 precursor = nullptr;
74 }
75 if (!precursor)
76 handle::resume();
77 }
78 if (handle::done()) {
79 auto x = await_resume();
80 handle::operator=(nullptr);
81 return x;
82 }
83 return {};
84 }
85
86 inline void task<void>::await_resume() const noexcept
87 {
88 handle::destroy();
89 }
90
91 template<typename other_t> void task<void>::await_suspend(std::coroutine_handle<task_promise<other_t>> h) const noexcept
92 {
93 h.promise().precursor = *this;
94 }
95
96 inline bool task<void>::operator()() noexcept
97 {
98 if (!handle::operator bool())
99 return true;
100 if (!handle::done()) {
101 auto &precursor = handle::promise().precursor;
102 if (precursor) {
103 if (!precursor.done())
104 precursor.resume();
105 if (precursor.done())
106 precursor = nullptr;
107 }
108 if (!precursor)
109 handle::resume();
110 }
111 if (handle::done()) {
112 await_resume();
113 handle::operator=(nullptr);
114 return true;
115 }
116 return false;
117 }
118
119}