-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtask.cpp
146 lines (117 loc) · 3.36 KB
/
task.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include <coroutine>
#include <iostream>
#include <memory>
using std::cout;
using std::endl;
// https://en.cppreference.com/w/cpp/coroutine/noop_coroutine
template <typename T>
auto addr(std::coroutine_handle<T> h) {
return (uint64_t)h.address() & (uint64_t)0xffff;
}
template <typename T>
struct Task {
struct promise_type {
Task<T> get_return_object() {
return Task<T>(std::coroutine_handle<promise_type>::from_promise(*this));
}
auto initial_suspend() { return std::suspend_always{}; }
auto final_suspend() noexcept {
struct FinalAwaiter {
bool await_ready() noexcept {
return false; // run await_suspend()
}
// Never run.
void await_resume() noexcept {}
std::coroutine_handle<> await_suspend(
std::coroutine_handle<promise_type> h) noexcept {
cout << addr(h) << " in final: await_suspend" << endl;
auto p = h.promise().parent_;
if (p) {
cout << "resume " << addr(p) << endl;
return p; // resume parent coroutine
}
cout << "No parent coroutine." << endl;
return std::noop_coroutine();
}
};
return FinalAwaiter{};
}
void unhandled_exception() { throw; }
// co_return
void return_value(T&& value) { result_ = std::forward<T>(value); }
T result_{};
std::coroutine_handle<> parent_;
};
// ===
auto operator co_await() {
struct Awaiter {
std::coroutine_handle<promise_type> h_;
bool await_ready() {
return false; // run await_suspend()
}
// co_await's return value
T await_resume() {
cout << addr(h_) << " in co_await: await_resume (to get return value)"
<< endl;
return std::move(h_.promise().result_);
}
auto await_suspend(std::coroutine_handle<> parent) {
cout << addr(parent) << " co_await " << addr(h_) << " await_suspend"
<< endl;
h_.promise().parent_ = parent;
return h_;
// (A co_await B;) Resume B with B's await_resume(). A's handle is
// stored in B (resume A in B's final_suspend()).
}
};
return Awaiter{h_};
}
T operator()() {
h_.resume();
return std::move(h_.promise().result_);
}
explicit Task(std::coroutine_handle<promise_type> h) : h_(h) {
cout << "Task(" << addr(h_) << ")" << endl;
}
~Task() {
cout << "~Task(" << addr(h_) << ")" << endl;
if (h_) h_.destroy();
}
private:
std::coroutine_handle<promise_type> h_;
};
Task<int> get_int() {
cout << "get_int()" << endl;
co_return 1;
}
Task<int> test() {
cout << "Task<int> test()" << endl;
Task<int> u = get_int();
cout << "u" << endl;
int v = co_await u;
cout << "v: " << v << endl;
Task<int> w = get_int();
co_return v + co_await w + co_await get_int();
};
Task<std::unique_ptr<int>> get_unique_ptr() {
co_return std::make_unique<int>(1);
}
Task<std::unique_ptr<int>> test2() {
auto u = get_unique_ptr();
auto v = co_await u;
co_return co_await get_unique_ptr();
}
int main() {
auto gi = get_int();
int giv = gi();
cout << "giv: " << giv << endl;
cout << "===" << endl;
auto t = test();
int result = t();
cout << "result: " << result << endl;
cout << "===" << endl;
auto t2 = test2();
auto result2 = t2();
cout << "result2: " << std::boolalpha << bool(result2) << endl;
return 0;
}