blob: 80a66f4a9e0554df04c246822146cdad4f27ef4c (
plain)
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
|
#pragma once
#include <coroutine>
template <typename T>
class promise_return {
private:
T val;
public:
void return_value(T v) {
val = v;
}
T value() {
return val;
}
};
template <>
class promise_return<void> {
public:
void return_void() {}
void value() {}
};
/// Coroutine future for asynchronous function. Implements \term{awaitable}, \term{co_await}, \term{co_return}.
///
/// \tparam T Return type.
///
/// Manages coroutine state.
/// Awaiting an empty object or destroying the coroutine state while it's being awaited results in undefined behavior.
///
template <typename T = void, typename initial_awaitable = std::suspend_always>
class async {
public:
class promise_type : public promise_return<T> {
public:
using handle_type = std::coroutine_handle<promise_type>;
async get_return_object() {
return {handle_type::from_promise(*this)};
}
std::coroutine_handle<> parent;
class final_awaitable {
public:
bool await_ready() { return false; }
std::coroutine_handle<> await_suspend(handle_type h) {
return h.promise().parent;
}
void await_resume() {}
};
initial_awaitable initial_suspend() { return {}; }
final_awaitable final_suspend() { return {}; }
};
bool await_ready() {
return handle.done();
}
auto await_suspend(std::coroutine_handle<> h) {
handle.promise().parent = h;
return handle;
}
T await_resume() {
return handle.promise().value();
}
/// Construct empty object.
async() : handle(nullptr) {}
/// Transfer ownership of coroutine state, leaving *other* empty.
async(async&& other) {
handle = other.handle;
other.handle = nullptr;
}
/// Transfer ownership of coroutine state, leaving *other* empty.
async& operator=(async&& other) {
handle = other.handle;
other.handle = nullptr;
return *this;
}
/// Destroy coroutine state if not empty.
~async() {
if(handle) {
handle.destroy();
}
}
private:
promise_type::handle_type handle;
async(promise_type::handle_type h) : handle(h) {}
async(const async&) = delete;
async& operator=(const async&) = delete;
};
|