Introduction to C++20 Coroutines - Part 4 Some examples about co_await

Coroutine in Python

In Python, in addition to passing data out from the coroutine, the outside can also pass information in.

1
2
3
4
5
6
7
8
9
10
11
from typing import Generator

def sequence() -> Generator[int, None, None]:
i = 0
while True:
yield i
i += 1

g = sequence()
for i in range(5):
print(next(g))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from typing import Generator

def sequence() -> Generator[int, None, None]:
i = 0
while True:
inside_receive = yield i
i += 1
print("inside receive:", inside_receive)


g = sequence()
next(g)

for i in range(3):
send_str = chr(ord('a')+i)
outside_receive = g.send(send_str)
print("outside receive:", outside_receive)

Output:

1
2
3
4
5
6
inside receive: a
outside receive: 1
inside receive: b
outside receive: 2
inside receive: c
outside receive: 3

Powerful C++ certainly also can!

Pass data bidirectionally with co_await

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
#include <coroutine>
#include <exception>
#include <iostream>

struct Generator {
struct promise_type {
Generator get_return_object() {
return Generator(std::coroutine_handle<promise_type>::from_promise(*this));
}
std::suspend_never initial_suspend() { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
void return_void() {}
void unhandled_exception() { std::terminate(); }

int in_to_out;
char out_to_in;
};

Generator(std::coroutine_handle<promise_type> handle) : m_coro_handle(handle) {}
~Generator() {
if (m_coro_handle) {
m_coro_handle.destroy();
}
}

bool done() {
return m_coro_handle.done();
}

int operator()(char out_to_in) {
int result = m_coro_handle.promise().in_to_out;

m_coro_handle.promise().out_to_in = out_to_in;
m_coro_handle.resume();

return result;
}

std::coroutine_handle<promise_type> m_coro_handle;
};

struct Awaiter {
Awaiter(int val) : m_value(val) {}
bool await_ready() { return false; }
void await_suspend(std::coroutine_handle<Generator::promise_type> handle) {
m_handle = handle;
m_handle.promise().in_to_out = m_value;
}
char await_resume() { return m_handle.promise().out_to_in; }

std::coroutine_handle<Generator::promise_type> m_handle;
int m_value;
};

Generator sequence() {
for (int i = 0; i < 3; ++i) {
char get_from_outside = co_await Awaiter{i};
std::cout << "get_from_outside: " << get_from_outside << std::endl;
}
}

int main() {
Generator g = sequence();
char send = 'a';
while (!g.done()) {
int receive = g(send++);
std::cout << "get_from_inside: " << receive << std::endl;
}

return 0;
}

Output:

1
2
3
4
5
6
get_from_outside: a
get_from_inside: 0
get_from_outside: b
get_from_inside: 1
get_from_outside: c
get_from_inside: 2

Introduction to C++20 Coroutines - Part 4 Some examples about co_await
http://wasprime.github.io/Dev/C++/STL/Coroutine/Introduction-to-C-20-Coroutines-Part-4-Some-examples-about-co-await/
Author
wasPrime
Posted on
April 29, 2023
Updated on
May 8, 2023
Licensed under