310
C++20 Coroutines Introduction Marcin Grzebieluch [email protected] 21.11.2019 grzebiel 21.11.2019 1 / 61

C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch [email protected] 21.11.2019 grzebiel 21.11.2019 2 / 61

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

C++20 CoroutinesIntroduction

Marcin Grzebieluch

[email protected]

21.11.2019

grzebiel 21.11.2019 1 / 61

Page 2: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

C++20 CoroutinesIntroduction

Marcin Grzebieluch

[email protected]

21.11.2019

grzebiel 21.11.2019 2 / 61

Page 3: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

grzebiel 21.11.2019 3 / 61

Page 4: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

Plan

1 why do we need coroutines

2 what is a coroutine

3 under the hood

4 implementing task coroutine

grzebiel 21.11.2019 4 / 61

Page 5: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

1 why do we need coroutines

2 what is a coroutine

3 under the hood

4 implementing task coroutine

why do we need coroutines grzebiel 21.11.2019 5 / 61

Page 6: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

my networking app1 std : : pair<blocking : : session , experiment> receive ( ) ;23 void program_main_loop()4 {5 thread_pool tp ;6 while ( true )7 {8 auto [ session , experiment] = receive ( ) ;9 tp . execute(

10 [s = std : :move( session ) , ex = std : :move(↪→ experiment) ] ( ) {

11 perform_experiment(ex , s ) ;12 }) ;13 }14 }

why do we need coroutines grzebiel 21.11.2019 6 / 61

Page 7: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

my networking app1 std : : pair<blocking : : session , experiment> receive ( ) ;23 void program_main_loop()4 {5 thread_pool tp;6 while ( true )7 {8 auto [ session , experiment] = receive ( ) ;9 tp . execute(

10 [s = std : :move( session ) , ex = std : :move(↪→ experiment) ] ( ) {

11 perform_experiment(ex , s ) ;12 }) ;13 }14 }

why do we need coroutines grzebiel 21.11.2019 6 / 61

Page 8: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

my networking app1 std : : pair<blocking : : session , experiment> receive ( ) ;23 void program_main_loop()4 {5 thread_pool tp;6 while(true)7 {8 auto [session, experiment] = receive();9 tp . execute(

10 [s = std : :move( session ) , ex = std : :move(↪→ experiment) ] ( ) {

11 perform_experiment(ex , s ) ;12 }) ;13 }14 }

why do we need coroutines grzebiel 21.11.2019 6 / 61

Page 9: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

my networking app1 std::pair<blocking::session, experiment> receive();23 void program_main_loop()4 {5 thread_pool tp;6 while(true)7 {8 auto [session, experiment] = receive();9 tp . execute(

10 [s = std : :move( session ) , ex = std : :move(↪→ experiment) ] ( ) {

11 perform_experiment(ex , s ) ;12 }) ;13 }14 }

why do we need coroutines grzebiel 21.11.2019 6 / 61

Page 10: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

my networking app1 std::pair<blocking::session, experiment> receive();23 void program_main_loop()4 {5 thread_pool tp;6 while(true)7 {8 auto [session, experiment] = receive();9 tp.execute(

10 [s = std::move(session), ex = std::move(↪→ experiment)]() {

11 perform_experiment(ex , s ) ;12 }) ;13 }14 }

why do we need coroutines grzebiel 21.11.2019 6 / 61

Page 11: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

my networking app1 std::pair<blocking::session, experiment> receive();23 void program_main_loop()4 {5 thread_pool tp;6 while(true)7 {8 auto [session, experiment] = receive();9 tp.execute(

10 [s = std::move(session), ex = std::move(↪→ experiment)]() {

11 perform_experiment(ex, s);12 });13 }14 }

why do we need coroutines grzebiel 21.11.2019 6 / 61

Page 12: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

my networking algorithm

1 using namespace blocking;2 void perform_experiment(experiment const& ex, session& s)3 {4 std : : vector<sample_result> results ;5 for ( auto const& sample : ex . samples)6 results .push_back(worker . analyze (sample) ) ;7 s . respond( results ) ;8 };

why do we need coroutines grzebiel 21.11.2019 7 / 61

Page 13: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

my networking algorithm

1 using namespace blocking;2 void perform_experiment(experiment const& ex, session& s)3 {4 std : : vector<sample_result> results ;5 for ( auto const& sample : ex . samples)6 results .push_back(worker . analyze (sample) ) ;7 s . respond( results ) ;8 };

why do we need coroutines grzebiel 21.11.2019 7 / 61

Page 14: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

my networking algorithm

1 using namespace blocking;2 void perform_experiment(experiment const& ex, session& s)3 {4 std::vector<sample_result> results;5 for ( auto const& sample : ex . samples)6 results .push_back(worker . analyze (sample) ) ;7 s . respond( results ) ;8 };

why do we need coroutines grzebiel 21.11.2019 7 / 61

Page 15: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

my networking algorithm

1 using namespace blocking;2 void perform_experiment(experiment const& ex, session& s)3 {4 std::vector<sample_result> results;5 for( auto const& sample : ex.samples)6 results .push_back(worker . analyze (sample) ) ;7 s . respond( results ) ;8 };

why do we need coroutines grzebiel 21.11.2019 7 / 61

Page 16: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

my networking algorithm

1 using namespace blocking;2 void perform_experiment(experiment const& ex, session& s)3 {4 std::vector<sample_result> results;5 for( auto const& sample : ex.samples)6 results.push_back(worker.analyze(sample));7 s . respond( results ) ;8 };

why do we need coroutines grzebiel 21.11.2019 7 / 61

Page 17: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

my networking algorithm

1 using namespace blocking;2 void perform_experiment(experiment const& ex, session& s)3 {4 std::vector<sample_result> results;5 for( auto const& sample : ex.samples)6 results.push_back(worker.analyze(sample));7 s.respond(results);8 };

why do we need coroutines grzebiel 21.11.2019 7 / 61

Page 18: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

my networking algorithm

why do we need coroutines grzebiel 21.11.2019 7 / 61

Page 19: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

problem

1 using namespace blocking;2 void perform_experiment(experiment const& ex, session& s)3 {4 std::vector<sample_result> results;5 for( auto const& sample : ex.samples)6 results.push_back(worker.analyze(sample));7 s.respond(results);8 };

why do we need coroutines grzebiel 21.11.2019 8 / 61

Page 20: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

problem

1 using namespace blocking ;2 void perform_experiment(experiment const& ex, session& s)3 {4 std : : vector<sample_result> results ;5 for ( auto const& sample : ex . samples)6 results.push_back(worker.analyze(sample));7 s . respond( results ) ;8 };

why do we need coroutines grzebiel 21.11.2019 8 / 61

Page 21: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

partial solution

why do we need coroutines grzebiel 21.11.2019 9 / 61

Page 22: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

partial solution

1 using namespace async;2 void perform_experiment(experiment const& ex, session& s) {3 std : : vector<std : : future<sample_result>> worker_futures ;4 for (auto const& s : ex . samples)5 worker_futures .push_back(worker . analyze (s ) ) ;67 std : : vector<sample_result> results ;8 for (auto& f : worker_futures )9 results .push_back( f . get ( ) ) ;

10 s . respond( results ) . get ( ) ;11 };

why do we need coroutines grzebiel 21.11.2019 10 / 61

Page 23: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

partial solution

1 using namespace async;2 void perform_experiment(experiment const& ex, session& s) {3 std::vector<std::future<sample_result>> worker_futures;4 for (auto const& s : ex . samples)5 worker_futures .push_back(worker . analyze (s ) ) ;67 std : : vector<sample_result> results ;8 for (auto& f : worker_futures )9 results .push_back( f . get ( ) ) ;

10 s . respond( results ) . get ( ) ;11 };

why do we need coroutines grzebiel 21.11.2019 10 / 61

Page 24: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

partial solution

1 using namespace async;2 void perform_experiment(experiment const& ex, session& s) {3 std::vector<std::future<sample_result>> worker_futures;4 for(auto const& s: ex.samples)5 worker_futures.push_back(worker.analyze(s));67 std : : vector<sample_result> results ;8 for (auto& f : worker_futures )9 results .push_back( f . get ( ) ) ;

10 s . respond( results ) . get ( ) ;11 };

why do we need coroutines grzebiel 21.11.2019 10 / 61

Page 25: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

partial solution

1 using namespace async;2 void perform_experiment(experiment const& ex, session& s) {3 std::vector<std::future<sample_result>> worker_futures;4 for(auto const& s: ex.samples)5 worker_futures.push_back(worker.analyze(s));67 std::vector<sample_result> results;8 for (auto& f : worker_futures )9 results .push_back( f . get ( ) ) ;

10 s . respond( results ) . get ( ) ;11 };

why do we need coroutines grzebiel 21.11.2019 10 / 61

Page 26: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

partial solution

1 using namespace async;2 void perform_experiment(experiment const& ex, session& s) {3 std::vector<std::future<sample_result>> worker_futures;4 for(auto const& s: ex.samples)5 worker_futures.push_back(worker.analyze(s));67 std::vector<sample_result> results;8 for (auto& f : worker_futures)9 results.push_back(f.get());

10 s . respond( results ) . get ( ) ;11 };

why do we need coroutines grzebiel 21.11.2019 10 / 61

Page 27: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

partial solution

1 using namespace async;2 void perform_experiment(experiment const& ex, session& s) {3 std::vector<std::future<sample_result>> worker_futures;4 for(auto const& s: ex.samples)5 worker_futures.push_back(worker.analyze(s));67 std::vector<sample_result> results;8 for (auto& f : worker_futures)9 results.push_back(f.get());

10 s.respond(results).get();11 };

why do we need coroutines grzebiel 21.11.2019 10 / 61

Page 28: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

how my application feels like

why do we need coroutines grzebiel 21.11.2019 11 / 61

Page 29: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

what I want from solution

why do we need coroutines grzebiel 21.11.2019 12 / 61

Page 30: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

what I want from solution

• reduce the amount of IO bound threads

why do we need coroutines grzebiel 21.11.2019 12 / 61

Page 31: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

what I want from solution

• reduce the amount of IO bound threads

• dont sacrafice readability

why do we need coroutines grzebiel 21.11.2019 12 / 61

Page 32: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

what I want from solution

• reduce the amount of IO bound threads

• dont sacrafice readability

• don’t force me to split my algorithm into artificialfunctions

why do we need coroutines grzebiel 21.11.2019 12 / 61

Page 33: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

1 why do we need coroutines

2 what is a coroutine

3 under the hood

4 implementing task coroutine

what is a coroutine grzebiel 21.11.2019 13 / 61

Page 34: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

lets start with subroutines

what is a coroutine grzebiel 21.11.2019 14 / 61

Page 35: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

lets start with subroutines

also known as functions

what is a coroutine grzebiel 21.11.2019 14 / 61

Page 36: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

lets start with subroutines

1 int foo(int a, int b) {2 int x = a + b;3 return x;4 }56 int main( ) {7 int x = foo (5 , 7) ;8 return x;9 }

what is a coroutine grzebiel 21.11.2019 14 / 61

Page 37: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

lets start with subroutines

1 int foo(int a, int b) {2 int x = a + b;3 return x;4 }56 int main( ) {7 int x = foo (5 , 7) ;8 return x;9 }

what is a coroutine grzebiel 21.11.2019 14 / 61

Page 38: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

lets start with subroutines

1 int foo(int a, int b) {2 int x = a + b;3 return x;4 }56 int main() {7 int x = foo (5 , 7) ;8 return x;9 }

what is a coroutine grzebiel 21.11.2019 14 / 61

Page 39: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

lets start with subroutines

1 int foo(int a, int b) {2 int x = a + b;3 return x;4 }56 int main() {7 int x = foo(5, 7);8 return x;9 }

what is a coroutine grzebiel 21.11.2019 14 / 61

Page 40: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

lets start with subroutines

1 int foo(int a, int b) {2 int x = a + b;3 return x;4 }56 int main() {7 int x = foo(5, 7);8 return x;9 }

what is a coroutine grzebiel 21.11.2019 14 / 61

Page 41: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

function call procedure

1 int foo ( int a , int b) {2 int x = a + b;3 return x;4 }56 int main() {7 int x = foo (5 , 7) ;8 return x;9 }

what is a coroutine grzebiel 21.11.2019 15 / 61

Page 42: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

function call procedure

1 int foo ( int a , int b) {2 int x = a + b;3 return x;4 }56 int main() {7 int x = foo(5, 7);8 return x;9 }

what is a coroutine grzebiel 21.11.2019 15 / 61

Page 43: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

function call procedure

1 int foo(int a, int b) {2 int x = a + b;3 return x;4 }56 int main() {7 int x = foo(5, 7);8 return x;9 }

what is a coroutine grzebiel 21.11.2019 15 / 61

Page 44: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

function call procedure

1 int foo ( int a , int b) {2 int x = a + b;3 return x;4 }56 int main() {7 int x = foo(5, 7);8 return x;9 }

what is a coroutine grzebiel 21.11.2019 15 / 61

Page 45: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

function call procedure

1 int foo ( int a , int b) {2 int x = a + b;3 return x;4 }56 int main() {7 int x = foo(5, 7);8 return x;9 }

what is a coroutine grzebiel 21.11.2019 15 / 61

Page 46: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

subroutine call actions

what is a coroutine grzebiel 21.11.2019 16 / 61

Page 47: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

subroutine call actions

• create stack frame

what is a coroutine grzebiel 21.11.2019 16 / 61

Page 48: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

subroutine call actions

• create stack frame

• execute function code

what is a coroutine grzebiel 21.11.2019 16 / 61

Page 49: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

subroutine call actions

• create stack frame

• execute function code

• return value

what is a coroutine grzebiel 21.11.2019 16 / 61

Page 50: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

subroutine call actions

• create stack frame

• execute function code

• return value

• delete stack frame

what is a coroutine grzebiel 21.11.2019 16 / 61

Page 51: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine call actions

• create stack frame

• execute function code

• return value

• delete stack frame

what is a coroutine grzebiel 21.11.2019 17 / 61

Page 52: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine call actions

• create stack frame

• execute function code

• return value

• delete stack frame

• suspend execution

what is a coroutine grzebiel 21.11.2019 17 / 61

Page 53: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine call actions

• create stack frame

• execute function code

• return value

• delete stack frame

• suspend execution

• resume execution

what is a coroutine grzebiel 21.11.2019 17 / 61

Page 54: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine

1 int foo(int a, int b) {2 int x = a + b;3 return x;4 }56 int main() {7 int x = foo(5, 7);8 return x;9 }

what is a coroutine grzebiel 21.11.2019 18 / 61

Page 55: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine

1 int foo(int a, int b) {2 int x = a + b;3 return x;4 }56 int main( ) {7 int x = foo (5 , 7) ;8 return x;9 }

what is a coroutine grzebiel 21.11.2019 18 / 61

Page 56: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine

1 task<int> foo(int a, int b) {2 int x = a + b;3 return x;4 }56 int main( ) {7 int x = foo (5 , 7) ;8 return x;9 }

what is a coroutine grzebiel 21.11.2019 18 / 61

Page 57: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine

1 task<int> foo(int a, int b) {2 int x = a + b;3 return x;4 }56 int main( ) {7 int x = foo (5 , 7) ;8 return x;9 }

what is a coroutine grzebiel 21.11.2019 18 / 61

Page 58: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine

1 task<int> foo(int a, int b) {2 int x = a + b;3 co_return x;4 }56 int main( ) {7 int x = foo (5 , 7) ;8 return x;9 }

what is a coroutine grzebiel 21.11.2019 18 / 61

Page 59: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine

1 task<int> foo(int a, int b) {2 int x = a + b;3 co_return x;4 }56 int main() {7 int x = foo(5, 7);8 return x;9 }

what is a coroutine grzebiel 21.11.2019 18 / 61

Page 60: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine

1 task<int> foo(int a, int b) {2 int x = a + b;3 co_return x;4 }56 int main() {7 task<int> x = foo(5, 7);8 return x;9 }

what is a coroutine grzebiel 21.11.2019 18 / 61

Page 61: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine

1 task<int> foo(int a, int b) {2 int x = a + b;3 co_return x;4 }56 int main() {7 task<int> x = foo(5, 7);8 return x;9 }

what is a coroutine grzebiel 21.11.2019 18 / 61

Page 62: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine

1 task<int> foo(int a, int b) {2 int x = a + b;3 co_return x;4 }56 int main() {7 task<int> x = foo(5, 7);8 x.resume();9 return x.result();

10 }

what is a coroutine grzebiel 21.11.2019 18 / 61

Page 63: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine

1 task<int> foo(int a, int b) {2 int x = a + b;3 co_return x;4 }56 int main( ) {7 task<int> x = foo(5 , 7) ;8 x .resume( ) ;9 return x . result ( ) ;

10 }

what is a coroutine grzebiel 21.11.2019 19 / 61

Page 64: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine

1 task<int> foo(int a, int b) {2 int x = a + b;3 co_await suspend_always{};4 co_return x;5 }67 int main( ) {8 task<int> x = foo(5 , 7) ;9 x .resume( ) ;

10 return x . result ( ) ;11 }

what is a coroutine grzebiel 21.11.2019 19 / 61

Page 65: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine

1 task<int> foo ( int a , int b) {2 int x = a + b;3 co_await suspend_always{};4 co_return x;5 }67 int main( ) {8 task<int> x = foo(5 , 7) ;9 x.resume();

10 return x . result ( ) ;11 }

what is a coroutine grzebiel 21.11.2019 19 / 61

Page 66: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine1 task<int> foo ( int a , int b) {2 int x = a + b;3 co_await suspend_always{};4 co_return x;5 }67 int main( ) {8 task<int> x = foo(5 , 7) ;9 x.resume();

10 x.resume();11 return x . result ( ) ;12 }

what is a coroutine grzebiel 21.11.2019 19 / 61

Page 67: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine1 task<int> foo ( int a , int b) {2 int x = a + b;3 co_await suspend_always{};4 co_return x;5 }67 int main( ) {8 task<int> x = foo(5 , 7) ;9 while(not x.is_ready())

10 x.resume();11 return x . result ( ) ;12 }

what is a coroutine grzebiel 21.11.2019 19 / 61

Page 68: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine1 task<int> foo(int a, int b) {2 int x = a + b;3 co_await suspend_always{};4 co_return x;5 }67 int main() {8 task<int> x = foo(5, 7);9 while(not x.is_ready())

10 x.resume();11 return x.result();12 }

what is a coroutine grzebiel 21.11.2019 19 / 61

Page 69: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine call procedure

1 task<int> foo(int a, int b) {2 int x = a + b;3 co_await suspend_always{};4 co_return x;5 }67 int main() {8 task<int> x = foo(5, 7);9 while(not x.is_ready())

10 x.resume();11 return x.result();12 }

what is a coroutine grzebiel 21.11.2019 20 / 61

Page 70: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine call procedure

1 task<int> foo ( int a , int b) {2 int x = a + b;3 co_await suspend_always{};4 co_return x;5 }67 int main() {8 task<int> x = foo(5 , 7) ;9 while (not x . is_ready ( ) )

10 x .resume( ) ;11 return x . result ( ) ;12 }

what is a coroutine grzebiel 21.11.2019 20 / 61

Page 71: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine call procedure

1 task<int> foo ( int a , int b) {2 int x = a + b;3 co_await suspend_always{};4 co_return x;5 }67 int main() {8 task<int> x = foo(5, 7);9 while (not x . is_ready ( ) )

10 x .resume( ) ;11 return x . result ( ) ;12 }

what is a coroutine grzebiel 21.11.2019 20 / 61

Page 72: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine call procedure

1 task<int> foo ( int a , int b) {2 int x = a + b;3 co_await suspend_always{};4 co_return x;5 }67 int main() {8 task<int> x = foo(5, 7);9 while (not x . is_ready ( ) )

10 x .resume( ) ;11 return x . result ( ) ;12 }

what is a coroutine grzebiel 21.11.2019 20 / 61

Page 73: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine call procedure

1 task<int> foo ( int a , int b) {2 int x = a + b;3 co_await suspend_always{};4 co_return x;5 }67 int main() {8 task<int> x = foo(5, 7);9 while (not x . is_ready ( ) )

10 x .resume( ) ;11 return x . result ( ) ;12 }

what is a coroutine grzebiel 21.11.2019 20 / 61

Page 74: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine call procedure

1 task<int> foo ( int a , int b) {2 int x = a + b;3 co_await suspend_always{};4 co_return x;5 }67 int main() {8 task<int> x = foo(5, 7);9 while(not x.is_ready())

10 x.resume();11 return x . result ( ) ;12 }

what is a coroutine grzebiel 21.11.2019 20 / 61

Page 75: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine call procedure

1 task<int> foo ( int a , int b) {2 int x = a + b;3 co_await suspend_always{};4 co_return x;5 }67 int main() {8 task<int> x = foo(5, 7);9 while(not x.is_ready())

10 x.resume();11 return x . result ( ) ;12 }

what is a coroutine grzebiel 21.11.2019 20 / 61

Page 76: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine call procedure

1 task<int> foo(int a, int b) {2 int x = a + b;3 co_await suspend_always{};4 co_return x;5 }67 int main() {8 task<int> x = foo(5, 7);9 while(not x.is_ready())

10 x.resume();11 return x . result ( ) ;12 }

what is a coroutine grzebiel 21.11.2019 20 / 61

Page 77: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine call procedure

1 task<int> foo ( int a , int b) {2 int x = a + b;3 co_await suspend_always{};4 co_return x;5 }67 int main() {8 task<int> x = foo(5, 7);9 while(not x.is_ready())

10 x.resume();11 return x . result ( ) ;12 }

what is a coroutine grzebiel 21.11.2019 20 / 61

Page 78: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine call procedure

1 task<int> foo ( int a , int b) {2 int x = a + b;3 co_await suspend_always{};4 co_return x;5 }67 int main() {8 task<int> x = foo(5, 7);9 while(not x.is_ready())

10 x.resume();11 return x.result();12 }

what is a coroutine grzebiel 21.11.2019 20 / 61

Page 79: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine call procedure

1 task<int> foo ( int a , int b) {2 int x = a + b;3 co_await suspend_always{};4 co_return x;5 }67 int main() {8 task<int> x = foo(5, 7);9 while(not x.is_ready())

10 x.resume();11 return x.result();12 }

what is a coroutine grzebiel 21.11.2019 20 / 61

Page 80: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine call procedure

1 task<int> foo ( int a , int b) {2 int x = a + b;3 co_await suspend_always{};4 co_return x;5 }67 int main() {8 task<int> x = foo(5, 7);9 while(not x.is_ready())

10 x.resume();11 return x.result();12 }

what is a coroutine grzebiel 21.11.2019 20 / 61

Page 81: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

previous slide was nightmare tomake

1 \ only<6>{\highlightedListing{7}{10}{cpp/ coroutine_call−m.hpp}2 \begin{textblock*}{5cm} (7cm,6.3cm)3 \ includegraphics [ scale=0.4]{dia / coroutine1_main}4 \end{textblock*}5 \ begin{textblock*}{5cm} (7.1cm,5.35cm)6 \ includegraphics [ scale=0.38]{dia / coroutine1_resume}7 \end{textblock*}8 \ begin{textblock*}{5cm} (11.61cm,5.05cm)9 \ includegraphics [ scale=0.43]{dia / coroutine1_foo_frame}

10 \end{textblock*}11 }

what is a coroutine grzebiel 21.11.2019 21 / 61

Page 82: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

previous slide was nightmare tomake

1 \ only<6>{\highlightedListing{7}{10}{cpp/ coroutine_call−m.hpp}2 \ begin{textblock*}{5cm} (7cm,6.3cm)3 \ includegraphics [ scale=0.4]{dia / coroutine1_main}4 \end{textblock*}5 \begin{textblock*}{5cm} (7.1cm,5.35cm)6 \ includegraphics [ scale=0.38]{dia / coroutine1_resume}7 \end{textblock*}8 \ begin{textblock*}{5cm} (11.61cm,5.05cm)9 \ includegraphics [ scale=0.43]{dia / coroutine1_foo_frame}

10 \end{textblock*}11 }

what is a coroutine grzebiel 21.11.2019 21 / 61

Page 83: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

previous slide was nightmare tomake

1 \ only<6>{\highlightedListing{7}{10}{cpp/ coroutine_call−m.hpp}2 \ begin{textblock*}{5cm} (7cm,6.3cm)3 \ includegraphics [ scale=0.4]{dia / coroutine1_main}4 \end{textblock*}5 \ begin{textblock*}{5cm} (7.1cm,5.35cm)6 \ includegraphics [ scale=0.38]{dia / coroutine1_resume}7 \end{textblock*}8 \begin{textblock*}{5cm} (11.61cm,5.05cm)9 \ includegraphics [ scale=0.43]{dia / coroutine1_foo_frame}

10 \end{textblock*}11 }

what is a coroutine grzebiel 21.11.2019 21 / 61

Page 84: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

previous slide was nightmare tomake

1 \ only<6>{\highlightedListing{7}{10}{cpp/ coroutine_call−m.hpp}2 \ begin{textblock*}{5cm} (7cm,6.3cm)3 \includegraphics[scale=0.4]{dia/coroutine1_main}4 \end{textblock*}5 \ begin{textblock*}{5cm} (7.1cm,5.35cm)6 \ includegraphics [ scale=0.38]{dia / coroutine1_resume}7 \end{textblock*}8 \ begin{textblock*}{5cm} (11.61cm,5.05cm)9 \ includegraphics [ scale=0.43]{dia / coroutine1_foo_frame}

10 \end{textblock*}11 }

what is a coroutine grzebiel 21.11.2019 21 / 61

Page 85: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

previous slide was nightmare tomake

1 \ only<6>{\highlightedListing{7}{10}{cpp/ coroutine_call−m.hpp}2 \ begin{textblock*}{5cm} (7cm,6.3cm)3 \ includegraphics [ scale=0.4]{dia / coroutine1_main}4 \end{textblock*}5 \ begin{textblock*}{5cm} (7.1cm,5.35cm)6 \includegraphics[scale=0.38]{dia/coroutine1_resume}7 \end{textblock*}8 \ begin{textblock*}{5cm} (11.61cm,5.05cm)9 \ includegraphics [ scale=0.43]{dia / coroutine1_foo_frame}

10 \end{textblock*}11 }

what is a coroutine grzebiel 21.11.2019 21 / 61

Page 86: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

previous slide was nightmare tomake

1 \ only<6>{\highlightedListing{7}{10}{cpp/ coroutine_call−m.hpp}2 \ begin{textblock*}{5cm} (7cm,6.3cm)3 \ includegraphics [ scale=0.4]{dia / coroutine1_main}4 \end{textblock*}5 \ begin{textblock*}{5cm} (7.1cm,5.35cm)6 \ includegraphics [ scale=0.38]{dia / coroutine1_resume}7 \end{textblock*}8 \ begin{textblock*}{5cm} (11.61cm,5.05cm)9 \includegraphics[scale=0.43]{dia/coroutine1_foo_frame}

10 \end{textblock*}11 }

what is a coroutine grzebiel 21.11.2019 21 / 61

Page 87: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

take away

what is a coroutine grzebiel 21.11.2019 22 / 61

Page 88: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

take away

• coroutine is a generalization of a function

what is a coroutine grzebiel 21.11.2019 22 / 61

Page 89: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

take away

• coroutine is a generalization of a function

• it can be suspended and resumed

what is a coroutine grzebiel 21.11.2019 22 / 61

Page 90: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

take away

• coroutine is a generalization of a function

• it can be suspended and resumed

• suspending and resuming is lightweight

what is a coroutine grzebiel 21.11.2019 22 / 61

Page 91: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

take away

• coroutine is a generalization of a function

• it can be suspended and resumed

• suspending and resuming is lightweight

• creating coroutine frame might require memoryallocation

• coroutines are stackless

what is a coroutine grzebiel 21.11.2019 22 / 61

Page 92: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

1 why do we need coroutines

2 what is a coroutine

3 under the hood

4 implementing task coroutine

under the hood grzebiel 21.11.2019 23 / 61

Page 93: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine transformation

1 task<int> bar(int a)2 {3 int b = 15;4 co_await suspend_always{};5 a = b * a;6 int c = b * 2;7 co_await suspend_always{};8 co_return a + b + c;9 }

under the hood grzebiel 21.11.2019 24 / 61

Page 94: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine transformation

1 task<int> bar(int a)2 {3 int b = 15;4 co_await suspend_always{};5 a = b * a;6 int c = b * 2;7 co_await suspend_always{};8 co_return a + b + c ;9 }

under the hood grzebiel 21.11.2019 24 / 61

Page 95: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine transformation

1 task<int> bar(int a)2 {3 int b = 15;4 co_await suspend_always{};5 a = b * a;6 int c = b * 2;7 co_await suspend_always{};8 co_return a + b + c ;9 }

1 struct _bar{2 int a;3 };

under the hood grzebiel 21.11.2019 24 / 61

Page 96: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine transformation

1 task<int> bar(int a)2 {3 int b = 15;4 co_await suspend_always{};5 a = b * a;6 int c = b * 2;7 co_await suspend_always{};8 co_return a + b + c ;9 }

1 struct _bar{2 _bar(int a_) : a{a_}{};3 int a;4 };

under the hood grzebiel 21.11.2019 24 / 61

Page 97: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine transformation

1 task<int> bar(int a)2 {3 int b = 15;4 co_await suspend_always{};5 a = b * a;6 int c = b * 2;7 co_await suspend_always{};8 co_return a + b + c ;9 }

1 struct _bar{2 _bar(int a_) : a{a_}{};3 int a;4 };

under the hood grzebiel 21.11.2019 24 / 61

Page 98: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine transformation

1 task<int> bar(int a)2 {3 int b = 15;4 co_await suspend_always{};5 a = b * a;6 int c = b * 2;7 co_await suspend_always{};8 co_return a + b + c ;9 }

1 struct _bar{2 _bar(int a_) : a{a_}{};3 void _s1(){ int b = 15; }4 int a;5 };

under the hood grzebiel 21.11.2019 24 / 61

Page 99: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine transformation

1 task<int> bar(int a)2 {3 int b = 15;4 co_await suspend_always{};5 a = b * a;6 int c = b * 2;7 co_await suspend_always{};8 co_return a + b + c ;9 }

1 struct _bar{2 _bar(int a_) : a{a_}{};3 void _s1(){ int b = 15; }4 int a;5 };

under the hood grzebiel 21.11.2019 24 / 61

Page 100: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine transformation

1 task<int> bar(int a)2 {3 int b = 15;4 co_await suspend_always{};5 a = b * a;6 int c = b * 2;7 co_await suspend_always{};8 co_return a + b + c ;9 }

1 struct _bar{2 _bar(int a_) : a{a_}{};3 void _s1(){ b = 15; }4 int a, b;5 };

under the hood grzebiel 21.11.2019 24 / 61

Page 101: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine transformation

1 task<int> bar(int a)2 {3 int b = 15;4 co_await suspend_always{};5 a = b * a;6 int c = b * 2;7 co_await suspend_always{};8 co_return a + b + c ;9 }

1 struct _bar{2 _bar(int a_) : a{a_}{};3 void _s1(){ b = 15; }4 void _s2(){ a = b * a; }5 int a, b;6 };

under the hood grzebiel 21.11.2019 24 / 61

Page 102: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine transformation

1 task<int> bar(int a)2 {3 int b = 15;4 co_await suspend_always{};5 a = b * a;6 int c = b * 2;7 co_await suspend_always{};8 co_return a + b + c ;9 }

1 struct _bar{2 _bar(int a_) : a{a_}{};3 void _s1(){ b = 15; }4 void _s2(){ a = b * a; }5 int a, b;6 };

under the hood grzebiel 21.11.2019 24 / 61

Page 103: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine transformation

1 task<int> bar(int a)2 {3 int b = 15;4 co_await suspend_always{};5 a = b * a;6 int c = b * 2;7 co_await suspend_always{};8 co_return a + b + c ;9 }

1 struct _bar{2 _bar(int a_) : a{a_}{};3 void _s1(){ b = 15; }4 void _s2(){5 a = b * a;6 int c = b * 2;7 }8 int a, b;9 };

under the hood grzebiel 21.11.2019 24 / 61

Page 104: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine transformation

1 task<int> bar(int a)2 {3 int b = 15;4 co_await suspend_always{};5 a = b * a;6 int c = b * 2;7 co_await suspend_always{};8 co_return a + b + c;9 }

1 struct _bar{2 _bar(int a_) : a{a_}{};3 void _s1(){ b = 15; }4 void _s2(){5 a = b * a;6 int c = b * 2;7 }8 int a, b;9 };

under the hood grzebiel 21.11.2019 24 / 61

Page 105: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine transformation

1 task<int> bar(int a)2 {3 int b = 15;4 co_await suspend_always{};5 a = b * a;6 int c = b * 2;7 co_await suspend_always{};8 co_return a + b + c;9 }

1 struct _bar{2 _bar(int a_) : a{a_}{};3 void _s1(){ b = 15; }4 void _s2(){5 a = b * a;6 c = b * 2;7 }8 int a, b, c;9 };

under the hood grzebiel 21.11.2019 24 / 61

Page 106: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine transformation1 task<int> bar(int a)2 {3 int b = 15;4 co_await suspend_always{};5 a = b * a;6 int c = b * 2;7 co_await suspend_always{};8 co_return a + b + c;9 }

1 struct _bar{2 _bar(int a_) : a{a_}{};3 void _s1(){ b = 15; }4 void _s2(){5 a = b * a;6 c = b * 2;7 }8 void _s3(){9 promise->return_value(

10 a + b + c);11 }12 int a, b, c, v;13 promise_type* promise;14 };

under the hood grzebiel 21.11.2019 24 / 61

Page 107: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine – recap

under the hood grzebiel 21.11.2019 25 / 61

Page 108: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine – recap

• coroutine body is transformed into coroutnine frame

under the hood grzebiel 21.11.2019 25 / 61

Page 109: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

coroutine – recap

• coroutine body is transformed into coroutnine frame

• each suspend point might end up as a separate function

under the hood grzebiel 21.11.2019 25 / 61

Page 110: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

1 why do we need coroutines

2 what is a coroutine

3 under the hood

4 implementing task coroutine

implementing task coroutine grzebiel 21.11.2019 26 / 61

Page 111: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type

implementing task coroutine grzebiel 21.11.2019 27 / 61

Page 112: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type

• interface type - task/generator/etc.

implementing task coroutine grzebiel 21.11.2019 27 / 61

Page 113: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type

• interface type - task/generator/etc.

• promise type

implementing task coroutine grzebiel 21.11.2019 27 / 61

Page 114: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type – task

1 #include "implementing_simple_task_promise−m.hpp"2 class task_{3 public :4 using promise_type = promise ;5 task_ ( coroutine_handle<promise> handle)6 : handle_ (handle)7 {}8 ~task_ ( ) { handle_ . destroy ( ) ; }9 private :

10 coroutine_handle<promise> handle_ ;11 };

implementing task coroutine grzebiel 21.11.2019 28 / 61

Page 115: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type – task

1 #include "implementing_simple_task_promise−m.hpp"2 class task_{3 public:4 using promise_type = promise;5 task_ ( coroutine_handle<promise> handle)6 : handle_ (handle)7 {}8 ~task_ ( ) { handle_ . destroy ( ) ; }9 private :

10 coroutine_handle<promise> handle_ ;11 };

implementing task coroutine grzebiel 21.11.2019 28 / 61

Page 116: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type – task

1 #include "implementing_simple_task_promise−m.hpp"2 class task_{3 public:4 using promise_type = promise;5 task_(coroutine_handle<promise> handle)6 : handle_(handle)7 {}8 ~task_ ( ) { handle_ . destroy ( ) ; }9 private :

10 coroutine_handle<promise> handle_ ;11 };

implementing task coroutine grzebiel 21.11.2019 28 / 61

Page 117: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type – task

1 #include "implementing_simple_task_promise−m.hpp"2 class task_{3 public:4 using promise_type = promise;5 task_(coroutine_handle<promise> handle)6 : handle_(handle)7 {}8 ~task_() { handle_.destroy(); }9 private :

10 coroutine_handle<promise> handle_ ;11 };

implementing task coroutine grzebiel 21.11.2019 28 / 61

Page 118: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type – task

1 #include "implementing_simple_task_promise−m.hpp"2 class task_{3 public:4 using promise_type = promise;5 task_(coroutine_handle<promise> handle)6 : handle_(handle)7 {}8 ~task_() { handle_.destroy(); }9 private:

10 coroutine_handle<promise> handle_;11 };

implementing task coroutine grzebiel 21.11.2019 28 / 61

Page 119: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type – task

1 #include "implementing_simple_task_promise−m.hpp"2 class task_{3 public :4 using promise_type = promise;5 task_ ( coroutine_handle<promise> handle)6 : handle_ (handle)7 {}8 ~task_ ( ) { handle_ . destroy ( ) ; }9 private :

10 coroutine_handle<promise> handle_ ;11 };

implementing task coroutine grzebiel 21.11.2019 28 / 61

Page 120: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type –promise

1 struct promise {2 auto get_return_object ( ) {3 return coroutine_handle<promise>::from_promise(* this ) ;4 }5 auto initial_suspend ( ) { return suspend_always ( ) ; }6 auto final_suspend ( ) { return suspend_always ( ) ; }7 void return_void ( ) {}8 void unhandled_exception ( ) {9 std : : terminate ( ) ;

10 }11 };12

implementing task coroutine grzebiel 21.11.2019 29 / 61

Page 121: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type –promise

1 struct promise {2 auto get_return_object() {3 return coroutine_handle<promise>::from_promise(*this);4 }5 auto initial_suspend ( ) { return suspend_always ( ) ; }6 auto final_suspend ( ) { return suspend_always ( ) ; }7 void return_void ( ) {}8 void unhandled_exception ( ) {9 std : : terminate ( ) ;

10 }11 };12

implementing task coroutine grzebiel 21.11.2019 29 / 61

Page 122: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type –promise

1 struct promise {2 auto get_return_object() {3 return coroutine_handle<promise>::from_promise(*this);4 }5 auto initial_suspend() { return suspend_always(); }6 auto final_suspend ( ) { return suspend_always ( ) ; }7 void return_void ( ) {}8 void unhandled_exception ( ) {9 std : : terminate ( ) ;

10 }11 };12

implementing task coroutine grzebiel 21.11.2019 29 / 61

Page 123: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type –promise

1 struct promise {2 auto get_return_object() {3 return coroutine_handle<promise>::from_promise(*this);4 }5 auto initial_suspend() { return suspend_always(); }6 auto final_suspend() { return suspend_always(); }7 void return_void ( ) {}8 void unhandled_exception ( ) {9 std : : terminate ( ) ;

10 }11 };12

implementing task coroutine grzebiel 21.11.2019 29 / 61

Page 124: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type –promise

1 struct promise {2 auto get_return_object() {3 return coroutine_handle<promise>::from_promise(*this);4 }5 auto initial_suspend() { return suspend_always(); }6 auto final_suspend() { return suspend_always(); }7 void return_void() {}8 void unhandled_exception ( ) {9 std : : terminate ( ) ;

10 }11 };12

implementing task coroutine grzebiel 21.11.2019 29 / 61

Page 125: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type –promise

1 struct promise {2 auto get_return_object() {3 return coroutine_handle<promise>::from_promise(*this);4 }5 auto initial_suspend() { return suspend_always(); }6 auto final_suspend() { return suspend_always(); }7 void return_void() {}8 void unhandled_exception() {9 std::terminate();

10 }11 };12

implementing task coroutine grzebiel 21.11.2019 29 / 61

Page 126: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type –usage

1 #include "implementing_simple_task_task−m.hpp"2 task_ foo()3 {4 std : : cout << " I am . . . " << std : : endl ;5 co_await suspend_always{};6 std : : cout << " . . . a COROUTINE! ! ! " << std : : endl ;7 }

implementing task coroutine grzebiel 21.11.2019 30 / 61

Page 127: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type –usage

1 #include "implementing_simple_task_task−m.hpp"2 task_ foo()3 {4 std::cout << "I am ..." << std::endl;5 co_await suspend_always{};6 std : : cout << " . . . a COROUTINE! ! ! " << std : : endl ;7 }

implementing task coroutine grzebiel 21.11.2019 30 / 61

Page 128: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type –usage

1 #include "implementing_simple_task_task−m.hpp"2 task_ foo()3 {4 std::cout << "I am ..." << std::endl;5 co_await suspend_always{};6 std : : cout << " . . . a COROUTINE! ! ! " << std : : endl ;7 }

implementing task coroutine grzebiel 21.11.2019 30 / 61

Page 129: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type –usage

1 #include "implementing_simple_task_task−m.hpp"2 task_ foo()3 {4 std::cout << "I am ..." << std::endl;5 co_await suspend_always{};6 std::cout << "...a COROUTINE!!!" << std::endl;7 }

implementing task coroutine grzebiel 21.11.2019 30 / 61

Page 130: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type –usage

1 #include "implementing_simple_task_task-m.hpp"2 task_ foo()3 {4 std::cout << "I am ..." << std::endl;5 co_await suspend_always{};6 std::cout << "...a COROUTINE!!!" << std::endl;7 co_return;8 }

implementing task coroutine grzebiel 21.11.2019 30 / 61

Page 131: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing coroutine type –usage

1 #include "implementing_simple_task_task-m.hpp"2 task_ foo()3 {4 std::cout << "I am ..." << std::endl;5 co_await suspend_always{};6 std::cout << "...a COROUTINE!!!" << std::endl;7 co_return 5; // error, no return_value(int)8 // in promise type9 }

implementing task coroutine grzebiel 21.11.2019 30 / 61

Page 132: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

returning value – promise

1 struct promise {2 auto get_return_object() {3 return coroutine_handle<promise>::from_promise(*this);4 }5 auto initial_suspend() { return suspend_always(); }6 auto final_suspend() { return suspend_always(); }7 void return_void() {}8 void unhandled_exception() {9 std::terminate();

10 }11 };12

implementing task coroutine grzebiel 21.11.2019 31 / 61

Page 133: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

returning value – promise

1 struct promise {2 auto get_return_object() {3 return coroutine_handle<promise>::from_promise(*this);4 }5 auto initial_suspend() { return suspend_always(); }6 auto final_suspend() { return suspend_always(); }7 void return_void() {}8 void unhandled_exception() {9 std::terminate();

10 }11 };12

implementing task coroutine grzebiel 21.11.2019 31 / 61

Page 134: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

returning value – promise

1 struct promise {2 //...3 void return_void() {}4 };

implementing task coroutine grzebiel 21.11.2019 31 / 61

Page 135: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

returning value – promise

1 struct promise {2 / / . . .3 void return_void ( ) {}4 };

implementing task coroutine grzebiel 21.11.2019 31 / 61

Page 136: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

returning value – promise

1 template <typename T>2 struct promise {3 T value_ ;4 / / . . .5 void return_void ( ) {}6 };7

implementing task coroutine grzebiel 21.11.2019 31 / 61

Page 137: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

returning value – promise

1 template <typename T>2 struct promise {3 T value_;4 //...5 void return_void() {}6 };7

implementing task coroutine grzebiel 21.11.2019 31 / 61

Page 138: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

returning value – promise

1 template <typename T>2 struct promise {3 T value_;4 //...5 void return_value(T t) { value_ = t; }6 };7

implementing task coroutine grzebiel 21.11.2019 31 / 61

Page 139: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

returning value – promise1 template <typename T>2 struct promise {3 T value_;4 auto get_return_object() {5 return coroutine_handle<promise>::from_promise(*this);6 }7 auto initial_suspend() { return suspend_always(); }8 auto final_suspend() { return suspend_always(); }9 void unhandled_exception() {

10 std::terminate();11 }12 void return_value(T t) { value_ = t; }13 };14

implementing task coroutine grzebiel 21.11.2019 31 / 61

Page 140: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

returning value – task

1 #include "implementing_simple_task_promise−m.hpp"2 class task_{3 public:4 using promise_type = promise;5 task_(coroutine_handle<promise> handle)6 : handle_(handle)7 {}8 ~task_() { handle_.destroy(); }9 private:

10 coroutine_handle<promise> handle_;11 };

implementing task coroutine grzebiel 21.11.2019 32 / 61

Page 141: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

returning value – task

1 #include "implementing_simple_task_promise−m.hpp"2 class task_{3 public :4 using promise_type = promise ;5 task_(coroutine_handle<promise> handle)6 : handle_(handle)7 {}8 ~task_() { handle_.destroy(); }9 private :

10 coroutine_handle<promise> handle_ ;11 };

implementing task coroutine grzebiel 21.11.2019 32 / 61

Page 142: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

returning value – task

1 #include "implementing_simple_task_promise−m.hpp"2 class task_{3 public :4 using promise_type = promise ;5 //...6 private :7 coroutine_handle<promise> handle_ ;8 };

implementing task coroutine grzebiel 21.11.2019 32 / 61

Page 143: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

returning value – task

1 #include "implementing_simple_task_promise−m.hpp"2 class task_{3 public :4 using promise_type = promise ;5 / / . . .6 private :7 coroutine_handle<promise> handle_ ;8 };

implementing task coroutine grzebiel 21.11.2019 32 / 61

Page 144: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

returning value – task

1 #include "implementing_returning_task_promise−m.hpp"2 template<typename T>3 class task_{4 public:5 using promise_type = promise<T>;6 //...7 private:8 coroutine_handle<promise<T>> handle_;9 };

implementing task coroutine grzebiel 21.11.2019 32 / 61

Page 145: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

returning value – task

1 #include "implementing_returning_task_promise−m.hpp"2 template<typename T>3 class task_{4 public:5 using promise_type = promise<T>;6 //...7 T value() { return handle_.promise().value_; }8 private:9 coroutine_handle<promise<T>> handle_;

10 };

implementing task coroutine grzebiel 21.11.2019 32 / 61

Page 146: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

using from subroutine

1 #include "using_returning_task−m.hpp"2 int main()3 {4 auto x = foo ( ) ;5 x .?? ;6 return x . value ( ) ;7 }

implementing task coroutine grzebiel 21.11.2019 33 / 61

Page 147: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

using from subroutine

1 #include "using_returning_task−m.hpp"2 int main()3 {4 auto x = foo();5 x .?? ;6 return x . value ( ) ;7 }

implementing task coroutine grzebiel 21.11.2019 33 / 61

Page 148: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

using from subroutine

1 #include "using_returning_task−m.hpp"2 int main()3 {4 auto x = foo();5 x.??;6 return x . value ( ) ;7 }

implementing task coroutine grzebiel 21.11.2019 33 / 61

Page 149: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

using from subroutine

1 #include "using_returning_task−m.hpp"2 int main()3 {4 auto x = foo();5 x.??;6 return x.value();7 }

implementing task coroutine grzebiel 21.11.2019 33 / 61

Page 150: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

usable task

1 #include "implementing_returning_task_promise−m.hpp"2 template<typename T>3 class task_{4 public:5 using promise_type = promise<T>;6 //...7 T value() { return handle_.promise().value_; }8 private:9 coroutine_handle<promise<T>> handle_;

10 };

implementing task coroutine grzebiel 21.11.2019 34 / 61

Page 151: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

usable task

1 #include "implementing_returning_task_promise−m.hpp"2 template<typename T>3 class task_{4 public :5 using promise_type = promise<T>;6 / / . . .7 T value ( ) { return handle_ . promise ( ) . value_ ; }8 T resume() { return handle_.resume(); }9 private :

10 coroutine_handle<promise<T>> handle_ ;11 };

implementing task coroutine grzebiel 21.11.2019 34 / 61

Page 152: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

usable task

1 #include "implementing_returning_task_promise−m.hpp"2 template<typename T>3 class task_{4 public :5 using promise_type = promise<T>;6 / / . . .7 T value ( ) { return handle_ . promise ( ) . value_ ; }8 T resume() { return handle_ .resume( ) ; }9 T is_ready() { return handle_.done(); }

10 private :11 coroutine_handle<promise<T>> handle_ ;12 };13

implementing task coroutine grzebiel 21.11.2019 34 / 61

Page 153: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

actual using from subroutine

1 #include "using_returning_task−m.hpp"2 int main( )3 {4 auto x = foo ( ) ;5 x.??;6 return x . value ( ) ;7 }

implementing task coroutine grzebiel 21.11.2019 35 / 61

Page 154: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

actual using from subroutine

1 #include "using_returning_task−m.hpp"2 int main( )3 {4 auto x = foo ( ) ;5 while( not x.is_ready() )6 x.resume();7 return x . value ( ) ;8 }

implementing task coroutine grzebiel 21.11.2019 35 / 61

Page 155: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

we did it!

implementing task coroutine grzebiel 21.11.2019 36 / 61

Page 156: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

we have the power!

implementing task coroutine grzebiel 21.11.2019 37 / 61

Page 157: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

we have the power!

• interface type - operate on coroutine

implementing task coroutine grzebiel 21.11.2019 37 / 61

Page 158: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

we have the power!

• interface type - operate on coroutine

• promise type - control coroutine behaviour

implementing task coroutine grzebiel 21.11.2019 37 / 61

Page 159: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

prefetching

1 struct data {};2 int costly_calculation (data&) ;3 task<int> prefetched_execution (data* d)4 {5 __buildin_prefetch (d, 1, 1) ;6 co_await suspend_always{};7 co_return costly_calculation (*d) ;8 };

implementing task coroutine grzebiel 21.11.2019 38 / 61

Page 160: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

prefetching

1 struct data {};2 int costly_calculation(data&);3 task<int> prefetched_execution (data* d)4 {5 __buildin_prefetch (d, 1, 1) ;6 co_await suspend_always{};7 co_return costly_calculation (*d) ;8 };

implementing task coroutine grzebiel 21.11.2019 38 / 61

Page 161: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

prefetching

1 struct data {};2 int costly_calculation(data&);3 task<int> prefetched_execution(data* d)4 {5 __buildin_prefetch (d, 1, 1) ;6 co_await suspend_always{};7 co_return costly_calculation (*d) ;8 };

implementing task coroutine grzebiel 21.11.2019 38 / 61

Page 162: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

prefetching

1 struct data {};2 int costly_calculation(data&);3 task<int> prefetched_execution(data* d)4 {5 __buildin_prefetch(d, 1, 1);6 co_await suspend_always{};7 co_return costly_calculation (*d) ;8 };

implementing task coroutine grzebiel 21.11.2019 38 / 61

Page 163: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

prefetching

1 struct data {};2 int costly_calculation(data&);3 task<int> prefetched_execution(data* d)4 {5 __buildin_prefetch(d, 1, 1);6 co_await suspend_always{};7 co_return costly_calculation (*d) ;8 };

implementing task coroutine grzebiel 21.11.2019 38 / 61

Page 164: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

prefetching

1 struct data {};2 int costly_calculation(data&);3 task<int> prefetched_execution(data* d)4 {5 __buildin_prefetch(d, 1, 1);6 co_await suspend_always{};7 co_return costly_calculation(*d);8 };

implementing task coroutine grzebiel 21.11.2019 38 / 61

Page 165: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

generator!

1 #include "generator−m.hpp"2 generator<int> foo() {3 for ( int i = 0; i < 10; ++i )4 co_yield i ;5 }67 int main( ) {8 auto x = foo ( ) ;9 std : : optional<int> i ;

10 while ( ( i = x . get_next ( ) ) != std : : nullopt )11 std : : cout << * i << std : : endl ;12 }

implementing task coroutine grzebiel 21.11.2019 39 / 61

Page 166: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

generator!

1 #include "generator−m.hpp"2 generator<int> foo() {3 for(int i = 0; i < 10; ++i)4 co_yield i;5 }67 int main( ) {8 auto x = foo ( ) ;9 std : : optional<int> i ;

10 while ( ( i = x . get_next ( ) ) != std : : nullopt )11 std : : cout << * i << std : : endl ;12 }

implementing task coroutine grzebiel 21.11.2019 39 / 61

Page 167: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

generator!

1 #include "generator−m.hpp"2 generator<int> foo() {3 for(int i = 0; i < 10; ++i)4 co_yield i;5 }67 int main() {8 auto x = foo();9 std : : optional<int> i ;

10 while ( ( i = x . get_next ( ) ) != std : : nullopt )11 std : : cout << * i << std : : endl ;12 }

implementing task coroutine grzebiel 21.11.2019 39 / 61

Page 168: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

generator!

1 #include "generator−m.hpp"2 generator<int> foo() {3 for(int i = 0; i < 10; ++i)4 co_yield i;5 }67 int main() {8 auto x = foo();9 std::optional<int> i;

10 while ( ( i = x . get_next ( ) ) != std : : nullopt )11 std : : cout << * i << std : : endl ;12 }

implementing task coroutine grzebiel 21.11.2019 39 / 61

Page 169: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

generator!

1 #include "generator−m.hpp"2 generator<int> foo() {3 for(int i = 0; i < 10; ++i)4 co_yield i;5 }67 int main() {8 auto x = foo();9 std::optional<int> i;

10 while((i = x.get_next()) != std::nullopt)11 std::cout << *i << std::endl;12 }

implementing task coroutine grzebiel 21.11.2019 39 / 61

Page 170: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

more generators!

1 #include "generator−m.hpp"2 generator<int> fib() {3 int a = 0, b = 1;4 while ( true ){5 co_yield b;6 int c = a + b;7 a = b;8 b = c ;9 };

10 }

implementing task coroutine grzebiel 21.11.2019 40 / 61

Page 171: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

more generators!

1 #include "generator−m.hpp"2 generator<int> fib() {3 int a = 0, b = 1;4 while ( true ){5 co_yield b;6 int c = a + b;7 a = b;8 b = c ;9 };

10 }

implementing task coroutine grzebiel 21.11.2019 40 / 61

Page 172: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

more generators!

1 #include "generator−m.hpp"2 generator<int> fib() {3 int a = 0, b = 1;4 while(true){5 co_yield b;6 int c = a + b;7 a = b;8 b = c ;9 };

10 }

implementing task coroutine grzebiel 21.11.2019 40 / 61

Page 173: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

more generators!

1 #include "generator−m.hpp"2 generator<int> fib() {3 int a = 0, b = 1;4 while(true){5 co_yield b;6 int c = a + b;7 a = b;8 b = c ;9 };

10 }

implementing task coroutine grzebiel 21.11.2019 40 / 61

Page 174: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

more generators!

1 #include "generator−m.hpp"2 generator<int> fib() {3 int a = 0, b = 1;4 while(true){5 co_yield b;6 int c = a + b;7 a = b;8 b = c;9 };

10 }

implementing task coroutine grzebiel 21.11.2019 40 / 61

Page 175: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing task coroutine grzebiel 21.11.2019 41 / 61

Page 176: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - interface

1 template <typename T>2 struct generator {3 struct promise_type ;4 coroutine_handle<promise_type> handle_ ;5 generator ( coroutine_handle<promise_type> handle)6 : handle_{handle}7 {}8 ~generator ( ) {9 i f (handle_ ) handle_ . destroy ( ) ;

10 }11 };

implementing task coroutine grzebiel 21.11.2019 42 / 61

Page 177: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - interface

1 template <typename T>2 struct generator {3 struct promise_type;4 coroutine_handle<promise_type> handle_ ;5 generator ( coroutine_handle<promise_type> handle)6 : handle_{handle}7 {}8 ~generator ( ) {9 i f (handle_ ) handle_ . destroy ( ) ;

10 }11 };

implementing task coroutine grzebiel 21.11.2019 42 / 61

Page 178: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - interface

1 template <typename T>2 struct generator {3 struct promise_type;4 coroutine_handle<promise_type> handle_;5 generator ( coroutine_handle<promise_type> handle)6 : handle_{handle}7 {}8 ~generator ( ) {9 i f (handle_ ) handle_ . destroy ( ) ;

10 }11 };

implementing task coroutine grzebiel 21.11.2019 42 / 61

Page 179: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - interface

1 template <typename T>2 struct generator {3 struct promise_type;4 coroutine_handle<promise_type> handle_;5 generator(coroutine_handle<promise_type> handle)6 : handle_{handle}7 {}8 ~generator ( ) {9 i f (handle_ ) handle_ . destroy ( ) ;

10 }11 };

implementing task coroutine grzebiel 21.11.2019 42 / 61

Page 180: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - interface

1 template <typename T>2 struct generator {3 struct promise_type;4 coroutine_handle<promise_type> handle_;5 generator(coroutine_handle<promise_type> handle)6 : handle_{handle}7 {}8 ~generator() {9 if(handle_) handle_.destroy();

10 }11 };

implementing task coroutine grzebiel 21.11.2019 42 / 61

Page 181: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - interface

1 template <typename T>2 struct generator {3 //...4 };

implementing task coroutine grzebiel 21.11.2019 42 / 61

Page 182: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - interface

1 template <typename T>2 struct generator {3 // ..4 std : : optional<T> get_next ( ) {5 handle_ .resume( ) ;6 i f (handle_ .done( ) )7 return std : : nullopt ;8 return handle_ . promise ( ) . current_value_ ;9 }

10 };

implementing task coroutine grzebiel 21.11.2019 42 / 61

Page 183: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - interface

1 template <typename T>2 struct generator {3 // ..4 std::optional<T> get_next() {5 handle_ .resume( ) ;6 i f (handle_ .done( ) )7 return std : : nullopt ;8 return handle_ . promise ( ) . current_value_ ;9 }

10 };

implementing task coroutine grzebiel 21.11.2019 42 / 61

Page 184: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - interface

1 template <typename T>2 struct generator {3 // ..4 std::optional<T> get_next() {5 handle_.resume();6 i f (handle_ .done( ) )7 return std : : nullopt ;8 return handle_ . promise ( ) . current_value_ ;9 }

10 };

implementing task coroutine grzebiel 21.11.2019 42 / 61

Page 185: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - interface

1 template <typename T>2 struct generator {3 // ..4 std::optional<T> get_next() {5 handle_.resume();6 if(handle_.done())7 return std::nullopt;8 return handle_ . promise ( ) . current_value_ ;9 }

10 };

implementing task coroutine grzebiel 21.11.2019 42 / 61

Page 186: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - interface

1 template <typename T>2 struct generator {3 // ..4 std::optional<T> get_next() {5 handle_.resume();6 if(handle_.done())7 return std::nullopt;8 return handle_.promise().current_value_;9 }

10 };

implementing task coroutine grzebiel 21.11.2019 42 / 61

Page 187: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - promise

1 template <typename T>2 struct generator<T>::promise_type {3 T current_value_ ;4 auto initial_suspend ( ) { return suspend_always{}; }5 auto final_suspend ( ) { return suspend_always{}; }6 void unhandled_exception ( ) {std : : terminate ( ) ;}7 auto get_return_object ( ) {8 return coroutine_handle<promise_type>::from_promise(* this ) ;9 }

10 auto yield_value (T value ) {11 this−>current_value_ = value ;12 return suspend_always{};13 }14 void return_void ( ) {};15 };

implementing task coroutine grzebiel 21.11.2019 43 / 61

Page 188: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - promise

1 template <typename T>2 struct generator<T>::promise_type {3 T current_value_;4 auto initial_suspend ( ) { return suspend_always{}; }5 auto final_suspend ( ) { return suspend_always{}; }6 void unhandled_exception ( ) {std : : terminate ( ) ;}7 auto get_return_object ( ) {8 return coroutine_handle<promise_type>::from_promise(* this ) ;9 }

10 auto yield_value (T value ) {11 this−>current_value_ = value ;12 return suspend_always{};13 }14 void return_void ( ) {};15 };

implementing task coroutine grzebiel 21.11.2019 43 / 61

Page 189: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - promise

1 template <typename T>2 struct generator<T>::promise_type {3 T current_value_;4 auto initial_suspend() { return suspend_always{}; }5 auto final_suspend() { return suspend_always{}; }6 void unhandled_exception ( ) {std : : terminate ( ) ;}7 auto get_return_object ( ) {8 return coroutine_handle<promise_type>::from_promise(* this ) ;9 }

10 auto yield_value (T value ) {11 this−>current_value_ = value ;12 return suspend_always{};13 }14 void return_void ( ) {};15 };

implementing task coroutine grzebiel 21.11.2019 43 / 61

Page 190: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - promise

1 template <typename T>2 struct generator<T>::promise_type {3 T current_value_;4 auto initial_suspend() { return suspend_always{}; }5 auto final_suspend() { return suspend_always{}; }6 void unhandled_exception() {std::terminate();}7 auto get_return_object ( ) {8 return coroutine_handle<promise_type>::from_promise(* this ) ;9 }

10 auto yield_value (T value ) {11 this−>current_value_ = value ;12 return suspend_always{};13 }14 void return_void ( ) {};15 };

implementing task coroutine grzebiel 21.11.2019 43 / 61

Page 191: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - promise

1 template <typename T>2 struct generator<T>::promise_type {3 T current_value_;4 auto initial_suspend() { return suspend_always{}; }5 auto final_suspend() { return suspend_always{}; }6 void unhandled_exception() {std::terminate();}7 auto get_return_object() {8 return coroutine_handle<promise_type>::from_promise(*this);9 }

10 auto yield_value (T value ) {11 this−>current_value_ = value ;12 return suspend_always{};13 }14 void return_void ( ) {};15 };

implementing task coroutine grzebiel 21.11.2019 43 / 61

Page 192: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - promise

1 template <typename T>2 struct generator<T>::promise_type {3 T current_value_;4 auto initial_suspend() { return suspend_always{}; }5 auto final_suspend() { return suspend_always{}; }6 void unhandled_exception() {std::terminate();}7 auto get_return_object() {8 return coroutine_handle<promise_type>::from_promise(*this);9 }

10 auto yield_value(T value) {11 this−>current_value_ = value ;12 return suspend_always{};13 }14 void return_void ( ) {};15 };

implementing task coroutine grzebiel 21.11.2019 43 / 61

Page 193: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - promise

1 template <typename T>2 struct generator<T>::promise_type {3 T current_value_;4 auto initial_suspend() { return suspend_always{}; }5 auto final_suspend() { return suspend_always{}; }6 void unhandled_exception() {std::terminate();}7 auto get_return_object() {8 return coroutine_handle<promise_type>::from_promise(*this);9 }

10 auto yield_value(T value) {11 this->current_value_ = value;12 return suspend_always{};13 }14 void return_void ( ) {};15 };

implementing task coroutine grzebiel 21.11.2019 43 / 61

Page 194: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - promise

1 template <typename T>2 struct generator<T>::promise_type {3 T current_value_;4 auto initial_suspend() { return suspend_always{}; }5 auto final_suspend() { return suspend_always{}; }6 void unhandled_exception() {std::terminate();}7 auto get_return_object() {8 return coroutine_handle<promise_type>::from_promise(*this);9 }

10 auto yield_value(T value) {11 this->current_value_ = value;12 return suspend_always{};13 }14 void return_void ( ) {};15 };

implementing task coroutine grzebiel 21.11.2019 43 / 61

Page 195: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

implementing generator - promise

1 template <typename T>2 struct generator<T>::promise_type {3 T current_value_;4 auto initial_suspend() { return suspend_always{}; }5 auto final_suspend() { return suspend_always{}; }6 void unhandled_exception() {std::terminate();}7 auto get_return_object() {8 return coroutine_handle<promise_type>::from_promise(*this);9 }

10 auto yield_value(T value) {11 this->current_value_ = value;12 return suspend_always{};13 }14 void return_void(){};15 };

implementing task coroutine grzebiel 21.11.2019 43 / 61

Page 196: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

its composable!

1 #include "generator−m.hpp"2 template<typename T>3 generator<T> take_at_most_n(generator<T> g,int n)4 {5 for (auto&& v : g)6 i f (n−− > 0)7 co_yield v ;8 else9 break ;

10 }

implementing task coroutine grzebiel 21.11.2019 44 / 61

Page 197: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

its composable!

1 #include "generator−m.hpp"2 template<typename T>3 generator<T> take_at_most_n(generator<T> g,int n)4 {5 for(auto&& v : g)6 i f (n−− > 0)7 co_yield v ;8 else9 break ;

10 }

implementing task coroutine grzebiel 21.11.2019 44 / 61

Page 198: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

its composable!

1 #include "generator−m.hpp"2 template<typename T>3 generator<T> take_at_most_n(generator<T> g,int n)4 {5 for(auto&& v : g)6 if(n-- > 0)7 co_yield v;8 else9 break ;

10 }

implementing task coroutine grzebiel 21.11.2019 44 / 61

Page 199: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

its composable!

1 #include "generator−m.hpp"2 template<typename T>3 generator<T> take_at_most_n(generator<T> g,int n)4 {5 for(auto&& v : g)6 if(n-- > 0)7 co_yield v;8 else9 break;

10 }

implementing task coroutine grzebiel 21.11.2019 44 / 61

Page 200: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

its composable!

1 #include "generator−m.hpp"2 template<typename T>3 generator<T> join(generator<T> g1, generator<T>

↪→ g2)4 {5 for ( auto&& v : g1 )6 co_yield v ;7 for ( auto&& v : g2 )8 co_yield v ;9 }

implementing task coroutine grzebiel 21.11.2019 44 / 61

Page 201: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

its composable!

1 #include "generator−m.hpp"2 template<typename T>3 generator<T> join(generator<T> g1, generator<T>

↪→ g2)4 {5 for( auto&& v : g1 )6 co_yield v;7 for ( auto&& v : g2 )8 co_yield v ;9 }

implementing task coroutine grzebiel 21.11.2019 44 / 61

Page 202: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

its composable!

1 #include "generator−m.hpp"2 template<typename T>3 generator<T> join(generator<T> g1, generator<T>

↪→ g2)4 {5 for( auto&& v : g1 )6 co_yield v;7 for( auto&& v : g2 )8 co_yield v;9 }

implementing task coroutine grzebiel 21.11.2019 44 / 61

Page 203: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

we almost have all the powers

• interface type - operate on coroutine

• promise type - control coroutine behaviour

implementing task coroutine grzebiel 21.11.2019 45 / 61

Page 204: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

we almost have all the powers

• interface type - operate on coroutine

• promise type - control coroutine behaviour

• awaiter type - control await behaviour

implementing task coroutine grzebiel 21.11.2019 45 / 61

Page 205: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

awaiting1 task<void> suspending() {2 std::cout << ", ";3 co_await suspend_always{};4 std::cout << "word";5 };67 task<void> composed( ) {8 std : : cout << " hello " ;9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 46 / 61

Page 206: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

awaiting1 task<void> suspending() {2 std::cout << ", ";3 co_await suspend_always{};4 std::cout << "word";5 };67 task<void> composed() {8 std::cout << "hello";9 co_await suspending();

10 std::cout << "!";11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 46 / 61

Page 207: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

awaiting1 task<void> suspending() {2 std::cout << ", ";3 co_await suspend_always{};4 std::cout << "word";5 };67 task<void> composed() {8 std::cout << "hello";9 co_await suspending();

10 std::cout << "!";11 };1213 int main() {14 task<void> x = composed();15 while(not x.is_ready())16 x.resume();17 }

implementing task coroutine grzebiel 21.11.2019 46 / 61

Page 208: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

awaiting1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std : : cout << "word" ;5 };67 task<void> composed( ) {8 std : : cout << " hello " ;9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main() {14 task<void> x = composed();15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 46 / 61

Page 209: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

awaiting1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std : : cout << "word" ;5 };67 task<void> composed() {8 std : : cout << " hello " ;9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 46 / 61

Page 210: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

awaiting1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std : : cout << "word" ;5 };67 task<void> composed() {8 std::cout << "hello";9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 46 / 61

output: hello

Page 211: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

awaiting1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std : : cout << "word" ;5 };67 task<void> composed() {8 std::cout << "hello";9 co_await suspending();

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 46 / 61

output: hello

Page 212: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

awaiting1 task<void> suspending() {2 std : : cout << " , " ;3 co_await suspend_always{};4 std : : cout << "word" ;5 };67 task<void> composed( ) {8 std : : cout << " hello " ;9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 46 / 61

output: hello

Page 213: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

awaiting1 task<void> suspending() {2 std::cout << ", ";3 co_await suspend_always{};4 std : : cout << "word" ;5 };67 task<void> composed( ) {8 std : : cout << " hello " ;9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 46 / 61

output: hello,

Page 214: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

awaiting1 task<void> suspending() {2 std::cout << ", ";3 co_await suspend_always{};4 std : : cout << "word" ;5 };67 task<void> composed( ) {8 std : : cout << " hello " ;9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 46 / 61

output: hello,

Page 215: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

awaiting1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std : : cout << "word" ;5 };67 task<void> composed( ) {8 std : : cout << " hello " ;9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while(not x.is_ready())16 x.resume();17 }

implementing task coroutine grzebiel 21.11.2019 46 / 61

output: hello,

Page 216: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

awaiting1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std::cout << "word";5 };67 task<void> composed( ) {8 std : : cout << " hello " ;9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 46 / 61

output: hello,

Page 217: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

awaiting1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std::cout << "word";5 };67 task<void> composed( ) {8 std : : cout << " hello " ;9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 46 / 61

output: hello, !

Page 218: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

awaiting1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std::cout << "word";5 };67 task<void> composed( ) {8 std : : cout << " hello " ;9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 46 / 61

output: hello, !

Page 219: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

how do we want to compose tasks1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std : : cout << "word" ;5 };67 task<void> composed( ) {8 std : : cout << " hello " ;9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main() {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 47 / 61

Page 220: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

how do we want to compose tasks1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std : : cout << "word" ;5 };67 task<void> composed( ) {8 std : : cout << " hello " ;9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main() {14 task<void> x = composed();15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 47 / 61

Page 221: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

how do we want to compose tasks1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std : : cout << "word" ;5 };67 task<void> composed( ) {8 std : : cout << " hello " ;9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main() {14 task<void> x = composed();15 while(not x.is_ready())16 x.resume();17 }

implementing task coroutine grzebiel 21.11.2019 47 / 61

Page 222: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

how do we want to compose tasks1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std : : cout << "word" ;5 };67 task<void> composed() {8 std::cout << "hello";9 co_await suspending();

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 47 / 61

Page 223: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

how do we want to compose tasks1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std : : cout << "word" ;5 };67 task<void> composed() {8 std::cout << "hello";9 co_await suspending();

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 47 / 61

Page 224: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

how do we want to compose tasks1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std : : cout << "word" ;5 };67 task<void> composed() {8 std::cout << "hello";9 co_await suspending();

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 47 / 61

Page 225: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

how do we want to compose tasks1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std : : cout << "word" ;5 };67 task<void> composed() {8 std::cout << "hello";9 co_await suspending();

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 47 / 61

Page 226: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

how do we want to compose tasks1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std : : cout << "word" ;5 };67 task<void> composed() {8 std::cout << "hello";9 co_await suspending();

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 47 / 61

Page 227: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

how do we want to compose tasks1 task<void> suspending() {2 std::cout << ", ";3 co_await suspend_always{};4 std : : cout << "word" ;5 };67 task<void> composed( ) {8 std : : cout << " hello " ;9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 47 / 61

Page 228: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

how do we want to compose tasks1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std : : cout << "word" ;5 };67 task<void> composed( ) {8 std : : cout << " hello " ;9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while(not x.is_ready())16 x.resume();17 }

implementing task coroutine grzebiel 21.11.2019 47 / 61

Page 229: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

how do we want to compose tasks1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std::cout << "word";5 };67 task<void> composed( ) {8 std : : cout << " hello " ;9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 47 / 61

Page 230: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

how do we want to compose tasks1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std::cout << "word";5 };67 task<void> composed( ) {8 std : : cout << " hello " ;9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 47 / 61

Page 231: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

how do we want to compose tasks1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std::cout << "word";5 };67 task<void> composed( ) {8 std : : cout << " hello " ;9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 47 / 61

Page 232: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

how do we want to compose tasks1 task<void> suspending ( ) {2 std : : cout << " , " ;3 co_await suspend_always{};4 std::cout << "word";5 };67 task<void> composed( ) {8 std : : cout << " hello " ;9 co_await suspending ( ) ;

10 std : : cout << " ! " ;11 };1213 int main( ) {14 task<void> x = composed( ) ;15 while (not x . is_ready ( ) )16 x .resume( ) ;17 }

implementing task coroutine grzebiel 21.11.2019 47 / 61

Page 233: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

begin of

slides removed from live presentation

implementing task coroutine grzebiel 21.11.2019 48 / 61

Page 234: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

trivial awaitable

1 struct suspend_always_

2 {3 bool await_ready ( ) { return false ; }4 void await_suspend(coroutine_handle<>) {}5 constexpr void await_resume( ) {}6 };

implementing task coroutine grzebiel 21.11.2019 49 / 61

Page 235: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

trivial awaitable

1 struct suspend_always_

2 {3 bool await_ready() { return false; }4 void await_suspend(coroutine_handle<>) {}5 constexpr void await_resume( ) {}6 };

implementing task coroutine grzebiel 21.11.2019 49 / 61

Page 236: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

trivial awaitable

1 struct suspend_always_

2 {3 bool await_ready() { return false; }4 void await_suspend(coroutine_handle<>) {}5 constexpr void await_resume( ) {}6 };

implementing task coroutine grzebiel 21.11.2019 49 / 61

Page 237: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

trivial awaitable

1 struct suspend_always_

2 {3 bool await_ready() { return false; }4 void await_suspend(coroutine_handle<>) {}5 constexpr void await_resume() {}6 };

implementing task coroutine grzebiel 21.11.2019 49 / 61

Page 238: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

make task awaitable

1 #include "awaitable−m.hpp"2 template<typename T>3 class task_{4 public :5 / / . . .67 auto operator co_await ( ) const & noexcept8 {9 return awaitable<T>{handle_};

10 }1112 private :13 coroutine_handle<promise<T>> handle_ ;14 };

implementing task coroutine grzebiel 21.11.2019 50 / 61

Page 239: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

make task awaitable

1 #include "awaitable−m.hpp"2 template<typename T>3 class task_{4 public:5 //...67 auto operator co_await ( ) const & noexcept8 {9 return awaitable<T>{handle_};

10 }1112 private :13 coroutine_handle<promise<T>> handle_ ;14 };

implementing task coroutine grzebiel 21.11.2019 50 / 61

Page 240: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

make task awaitable

1 #include "awaitable−m.hpp"2 template<typename T>3 class task_{4 public:5 //...67 auto operator co_await() const & noexcept8 {9 return awaitable<T>{handle_};

10 }1112 private :13 coroutine_handle<promise<T>> handle_ ;14 };

implementing task coroutine grzebiel 21.11.2019 50 / 61

Page 241: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

make task awaitable

1 #include "awaitable−m.hpp"2 template<typename T>3 class task_{4 public:5 //...67 auto operator co_await() const & noexcept8 {9 return awaitable<T>{handle_};

10 }1112 private :13 coroutine_handle<promise<T>> handle_ ;14 };

implementing task coroutine grzebiel 21.11.2019 50 / 61

Page 242: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

make task awaitable

1 #include "awaitable−m.hpp"2 template<typename T>3 class task_{4 public:5 //...67 auto operator co_await() const & noexcept8 {9 return awaitable<T>{handle_};

10 }1112 private :13 coroutine_handle<promise<T>> handle_ ;14 };

implementing task coroutine grzebiel 21.11.2019 50 / 61

Page 243: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

make task awaitable

1 #include "awaitable−m.hpp"2 template<typename T>3 class task_{4 public:5 //...67 auto operator co_await() const & noexcept8 {9 return awaitable<T>{handle_};

10 }1112 private :13 coroutine_handle<promise<T>> handle_ ;14 };

implementing task coroutine grzebiel 21.11.2019 50 / 61

Page 244: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

our awaitable1 #include "awaitable_promise−m.hpp"2 template <typename T>3 struct awaitable4 {5 coroutine_handle<promise<T>> coro_ ;6 awaitable ( coroutine_handle<promise<T>> coro ) : coro_{coro}{};78 bool await_ready ( ) { return not coro_ .done( ) ; }9 coroutine_handle<> await_suspend(coroutine_handle<> awaitingCoro ) {

10 coro_ . promise ( ) . set_continuation (awaitingCoro ) ;11 return coro_ ;12 }13 decltype (auto) await_resume( ) {14 return coro_ . promise ( ) . value_ ;15 }16 };

implementing task coroutine grzebiel 21.11.2019 51 / 61

Page 245: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

our awaitable1 #include "awaitable_promise−m.hpp"2 template <typename T>3 struct awaitable4 {5 coroutine_handle<promise<T>> coro_;6 awaitable(coroutine_handle<promise<T>> coro) : coro_{coro}{};78 bool await_ready ( ) { return not coro_ .done( ) ; }9 coroutine_handle<> await_suspend(coroutine_handle<> awaitingCoro ) {

10 coro_ . promise ( ) . set_continuation (awaitingCoro ) ;11 return coro_ ;12 }13 decltype (auto) await_resume( ) {14 return coro_ . promise ( ) . value_ ;15 }16 };

implementing task coroutine grzebiel 21.11.2019 51 / 61

Page 246: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

our awaitable1 #include "awaitable_promise−m.hpp"2 template <typename T>3 struct awaitable4 {5 coroutine_handle<promise<T>> coro_;6 awaitable(coroutine_handle<promise<T>> coro) : coro_{coro}{};78 bool await_ready() { return not coro_.done(); }9 coroutine_handle<> await_suspend(coroutine_handle<> awaitingCoro ) {

10 coro_ . promise ( ) . set_continuation (awaitingCoro ) ;11 return coro_ ;12 }13 decltype (auto) await_resume( ) {14 return coro_ . promise ( ) . value_ ;15 }16 };

implementing task coroutine grzebiel 21.11.2019 51 / 61

Page 247: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

our awaitable1 #include "awaitable_promise−m.hpp"2 template <typename T>3 struct awaitable4 {5 coroutine_handle<promise<T>> coro_;6 awaitable(coroutine_handle<promise<T>> coro) : coro_{coro}{};78 bool await_ready() { return not coro_.done(); }9 coroutine_handle<> await_suspend(coroutine_handle<> awaitingCoro) {

10 coro_ . promise ( ) . set_continuation (awaitingCoro ) ;11 return coro_ ;12 }13 decltype (auto) await_resume( ) {14 return coro_ . promise ( ) . value_ ;15 }16 };

implementing task coroutine grzebiel 21.11.2019 51 / 61

Page 248: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

our awaitable1 #include "awaitable_promise−m.hpp"2 template <typename T>3 struct awaitable4 {5 coroutine_handle<promise<T>> coro_;6 awaitable(coroutine_handle<promise<T>> coro) : coro_{coro}{};78 bool await_ready() { return not coro_.done(); }9 coroutine_handle<> await_suspend(coroutine_handle<> awaitingCoro) {

10 coro_ . promise ( ) . set_continuation (awaitingCoro ) ;11 return coro_ ;12 }13 decltype (auto) await_resume( ) {14 return coro_ . promise ( ) . value_ ;15 }16 };

implementing task coroutine grzebiel 21.11.2019 51 / 61

Page 249: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

our awaitable1 #include "awaitable_promise−m.hpp"2 template <typename T>3 struct awaitable4 {5 coroutine_handle<promise<T>> coro_;6 awaitable(coroutine_handle<promise<T>> coro) : coro_{coro}{};78 bool await_ready() { return not coro_.done(); }9 coroutine_handle<> await_suspend(coroutine_handle<> awaitingCoro) {

10 coro_ . promise ( ) . set_continuation (awaitingCoro ) ;11 return coro_ ;12 }13 decltype (auto) await_resume( ) {14 return coro_ . promise ( ) . value_ ;15 }16 };

implementing task coroutine grzebiel 21.11.2019 51 / 61

Page 250: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

our awaitable1 #include "awaitable_promise−m.hpp"2 template <typename T>3 struct awaitable4 {5 coroutine_handle<promise<T>> coro_;6 awaitable(coroutine_handle<promise<T>> coro) : coro_{coro}{};78 bool await_ready() { return not coro_.done(); }9 coroutine_handle<> await_suspend(coroutine_handle<> awaitingCoro) {

10 coro_ . promise ( ) . set_continuation (awaitingCoro ) ;11 return coro_ ;12 }13 decltype (auto) await_resume( ) {14 return coro_ . promise ( ) . value_ ;15 }16 };

implementing task coroutine grzebiel 21.11.2019 51 / 61

Page 251: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

our awaitable1 #include "awaitable_promise−m.hpp"2 template <typename T>3 struct awaitable4 {5 coroutine_handle<promise<T>> coro_;6 awaitable(coroutine_handle<promise<T>> coro) : coro_{coro}{};78 bool await_ready() { return not coro_.done(); }9 coroutine_handle<> await_suspend(coroutine_handle<> awaitingCoro) {

10 coro_.promise().set_continuation(awaitingCoro);11 return coro_ ;12 }13 decltype (auto) await_resume( ) {14 return coro_ . promise ( ) . value_ ;15 }16 };

implementing task coroutine grzebiel 21.11.2019 51 / 61

Page 252: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

our awaitable1 #include "awaitable_promise−m.hpp"2 template <typename T>3 struct awaitable4 {5 coroutine_handle<promise<T>> coro_;6 awaitable(coroutine_handle<promise<T>> coro) : coro_{coro}{};78 bool await_ready() { return not coro_.done(); }9 coroutine_handle<> await_suspend(coroutine_handle<> awaitingCoro) {

10 coro_.promise().set_continuation(awaitingCoro);11 return coro_ ;12 }13 decltype (auto) await_resume( ) {14 return coro_ . promise ( ) . value_ ;15 }16 };

implementing task coroutine grzebiel 21.11.2019 51 / 61

Page 253: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

our awaitable1 #include "awaitable_promise−m.hpp"2 template <typename T>3 struct awaitable4 {5 coroutine_handle<promise<T>> coro_;6 awaitable(coroutine_handle<promise<T>> coro) : coro_{coro}{};78 bool await_ready() { return not coro_.done(); }9 coroutine_handle<> await_suspend(coroutine_handle<> awaitingCoro) {

10 coro_.promise().set_continuation(awaitingCoro);11 return coro_ ;12 }13 decltype (auto) await_resume( ) {14 return coro_ . promise ( ) . value_ ;15 }16 };

implementing task coroutine grzebiel 21.11.2019 51 / 61

Page 254: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

our awaitable1 #include "awaitable_promise−m.hpp"2 template <typename T>3 struct awaitable4 {5 coroutine_handle<promise<T>> coro_;6 awaitable(coroutine_handle<promise<T>> coro) : coro_{coro}{};78 bool await_ready() { return not coro_.done(); }9 coroutine_handle<> await_suspend(coroutine_handle<> awaitingCoro) {

10 coro_.promise().set_continuation(awaitingCoro);11 return coro_;12 }13 decltype (auto) await_resume( ) {14 return coro_ . promise ( ) . value_ ;15 }16 };

implementing task coroutine grzebiel 21.11.2019 51 / 61

Page 255: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

our awaitable1 #include "awaitable_promise−m.hpp"2 template <typename T>3 struct awaitable4 {5 coroutine_handle<promise<T>> coro_;6 awaitable(coroutine_handle<promise<T>> coro) : coro_{coro}{};78 bool await_ready() { return not coro_.done(); }9 coroutine_handle<> await_suspend(coroutine_handle<> awaitingCoro) {

10 coro_.promise().set_continuation(awaitingCoro);11 return coro_;12 }13 decltype (auto) await_resume( ) {14 return coro_ . promise ( ) . value_ ;15 }16 };

implementing task coroutine grzebiel 21.11.2019 51 / 61

Page 256: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

our awaitable1 #include "awaitable_promise−m.hpp"2 template <typename T>3 struct awaitable4 {5 coroutine_handle<promise<T>> coro_;6 awaitable(coroutine_handle<promise<T>> coro) : coro_{coro}{};78 bool await_ready() { return not coro_.done(); }9 coroutine_handle<> await_suspend(coroutine_handle<> awaitingCoro) {

10 coro_.promise().set_continuation(awaitingCoro);11 return coro_;12 }13 decltype (auto) await_resume( ) {14 return coro_ . promise ( ) . value_ ;15 }16 };

implementing task coroutine grzebiel 21.11.2019 51 / 61

Page 257: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

our awaitable1 #include "awaitable_promise−m.hpp"2 template <typename T>3 struct awaitable4 {5 coroutine_handle<promise<T>> coro_;6 awaitable(coroutine_handle<promise<T>> coro) : coro_{coro}{};78 bool await_ready() { return not coro_.done(); }9 coroutine_handle<> await_suspend(coroutine_handle<> awaitingCoro) {

10 coro_.promise().set_continuation(awaitingCoro);11 return coro_;12 }13 decltype (auto) await_resume( ) {14 return coro_ . promise ( ) . value_ ;15 }16 };

implementing task coroutine grzebiel 21.11.2019 51 / 61

Page 258: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

our awaitable1 #include "awaitable_promise−m.hpp"2 template <typename T>3 struct awaitable4 {5 coroutine_handle<promise<T>> coro_;6 awaitable(coroutine_handle<promise<T>> coro) : coro_{coro}{};78 bool await_ready() { return not coro_.done(); }9 coroutine_handle<> await_suspend(coroutine_handle<> awaitingCoro) {

10 coro_.promise().set_continuation(awaitingCoro);11 return coro_;12 }13 decltype(auto) await_resume() {14 return coro_.promise().value_;15 }16 };

implementing task coroutine grzebiel 21.11.2019 51 / 61

Page 259: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

setting continuation1 #include " final_awaitable−m.hpp"2 template <typename T>3 struct promise {4 / / . . .56 coroutine_handle<> continuation_ ;7 void set_continuation ( coroutine_handle<> continuation ) {8 continuation_ = continuation ;9 }

1011 auto final_suspend ( ) { return final_awaitable{}; }1213 };14

implementing task coroutine grzebiel 21.11.2019 52 / 61

Page 260: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

setting continuation1 #include " final_awaitable−m.hpp"2 template <typename T>3 struct promise {4 // ...56 coroutine_handle<> continuation_ ;7 void set_continuation ( coroutine_handle<> continuation ) {8 continuation_ = continuation ;9 }

1011 auto final_suspend ( ) { return final_awaitable{}; }1213 };14

implementing task coroutine grzebiel 21.11.2019 52 / 61

Page 261: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

setting continuation1 #include " final_awaitable−m.hpp"2 template <typename T>3 struct promise {4 // ...56 coroutine_handle<> continuation_;7 void set_continuation ( coroutine_handle<> continuation ) {8 continuation_ = continuation ;9 }

1011 auto final_suspend ( ) { return final_awaitable{}; }1213 };14

implementing task coroutine grzebiel 21.11.2019 52 / 61

Page 262: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

setting continuation1 #include " final_awaitable−m.hpp"2 template <typename T>3 struct promise {4 // ...56 coroutine_handle<> continuation_;7 void set_continuation(coroutine_handle<> continuation) {8 continuation_ = continuation;9 }

1011 auto final_suspend ( ) { return final_awaitable{}; }1213 };14

implementing task coroutine grzebiel 21.11.2019 52 / 61

Page 263: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

setting continuation1 #include " final_awaitable−m.hpp"2 template <typename T>3 struct promise {4 // ...56 coroutine_handle<> continuation_;7 void set_continuation(coroutine_handle<> continuation) {8 continuation_ = continuation;9 }

1011 auto final_suspend ( ) { return final_awaitable{}; }1213 };14

implementing task coroutine grzebiel 21.11.2019 52 / 61

Page 264: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

setting continuation1 #include " final_awaitable−m.hpp"2 template <typename T>3 struct promise {4 // ...56 coroutine_handle<> continuation_;7 void set_continuation(coroutine_handle<> continuation) {8 continuation_ = continuation;9 }

1011 auto final_suspend ( ) { return final_awaitable{}; }1213 };14

implementing task coroutine grzebiel 21.11.2019 52 / 61

Page 265: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

setting continuation1 #include " final_awaitable−m.hpp"2 template <typename T>3 struct promise {4 // ...56 coroutine_handle<> continuation_;7 void set_continuation(coroutine_handle<> continuation) {8 continuation_ = continuation;9 }

1011 auto final_suspend ( ) { return final_awaitable{}; }1213 };14

implementing task coroutine grzebiel 21.11.2019 52 / 61

Page 266: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

setting continuation1 #include " final_awaitable−m.hpp"2 template <typename T>3 struct promise {4 // ...56 coroutine_handle<> continuation_;7 void set_continuation(coroutine_handle<> continuation) {8 continuation_ = continuation;9 }

1011 auto final_suspend() { return final_awaitable{}; }1213 };14

implementing task coroutine grzebiel 21.11.2019 52 / 61

Page 267: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

setting continuation1 #include " final_awaitable−m.hpp"2 template <typename T>3 struct promise {4 // ...56 coroutine_handle<> continuation_;7 void set_continuation(coroutine_handle<> continuation) {8 continuation_ = continuation;9 }

1011 auto final_suspend() { return final_awaitable{}; }1213 };14

implementing task coroutine grzebiel 21.11.2019 52 / 61

Page 268: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

setting continuation1 #include " final_awaitable−m.hpp"2 template <typename T>3 struct promise {4 // ...56 coroutine_handle<> continuation_;7 void set_continuation(coroutine_handle<> continuation) {8 continuation_ = continuation;9 }

1011 auto final_suspend() { return final_awaitable{}; }1213 };14

implementing task coroutine grzebiel 21.11.2019 52 / 61

Page 269: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

setting continuation1 #include " final_awaitable−m.hpp"2 template <typename T>3 struct promise {4 // ...56 coroutine_handle<> continuation_;7 void set_continuation(coroutine_handle<> continuation) {8 continuation_ = continuation;9 }

1011 auto final_suspend() { return final_awaitable{}; }1213 };14

implementing task coroutine grzebiel 21.11.2019 52 / 61

Page 270: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

final suspend - final awaitable

1 struct final_awaitable2 {3 bool await_ready ( ) { return false ;};4 void await_resume( ) noexcept{}56 template <typename P>7 coroutine_handle<> await_suspend(coroutine_handle<P> finalizedCoro )8 {9 return finalizedCoro . promise ( ) . continuation_ ;

10 }11 };

implementing task coroutine grzebiel 21.11.2019 53 / 61

Page 271: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

final suspend - final awaitable

1 struct final_awaitable2 {3 bool await_ready() { return false;};4 void await_resume( ) noexcept{}56 template <typename P>7 coroutine_handle<> await_suspend(coroutine_handle<P> finalizedCoro )8 {9 return finalizedCoro . promise ( ) . continuation_ ;

10 }11 };

implementing task coroutine grzebiel 21.11.2019 53 / 61

Page 272: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

final suspend - final awaitable

1 struct final_awaitable2 {3 bool await_ready() { return false;};4 void await_resume() noexcept{}56 template <typename P>7 coroutine_handle<> await_suspend(coroutine_handle<P> finalizedCoro )8 {9 return finalizedCoro . promise ( ) . continuation_ ;

10 }11 };

implementing task coroutine grzebiel 21.11.2019 53 / 61

Page 273: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

final suspend - final awaitable

1 struct final_awaitable2 {3 bool await_ready() { return false;};4 void await_resume() noexcept{}56 template <typename P>7 coroutine_handle<> await_suspend(coroutine_handle<P> finalizedCoro)8 {9 return finalizedCoro . promise ( ) . continuation_ ;

10 }11 };

implementing task coroutine grzebiel 21.11.2019 53 / 61

Page 274: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

final suspend - final awaitable

1 struct final_awaitable2 {3 bool await_ready() { return false;};4 void await_resume() noexcept{}56 template <typename P>7 coroutine_handle<> await_suspend(coroutine_handle<P> finalizedCoro)8 {9 return finalizedCoro . promise ( ) . continuation_ ;

10 }11 };

implementing task coroutine grzebiel 21.11.2019 53 / 61

Page 275: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

final suspend - final awaitable

1 struct final_awaitable2 {3 bool await_ready() { return false;};4 void await_resume() noexcept{}56 template <typename P>7 coroutine_handle<> await_suspend(coroutine_handle<P> finalizedCoro)8 {9 return finalizedCoro . promise ( ) . continuation_ ;

10 }11 };

implementing task coroutine grzebiel 21.11.2019 53 / 61

Page 276: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

final suspend - final awaitable

1 struct final_awaitable2 {3 bool await_ready() { return false;};4 void await_resume() noexcept{}56 template <typename P>7 coroutine_handle<> await_suspend(coroutine_handle<P> finalizedCoro)8 {9 return finalizedCoro.promise().continuation_;

10 }11 };

implementing task coroutine grzebiel 21.11.2019 53 / 61

Page 277: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

final suspend - final awaitable

1 struct final_awaitable2 {3 bool await_ready() { return false;};4 void await_resume() noexcept{}56 template <typename P>7 coroutine_handle<> await_suspend(coroutine_handle<P> finalizedCoro)8 {9 return finalizedCoro.promise().continuation_;

10 }11 };

implementing task coroutine grzebiel 21.11.2019 53 / 61

Page 278: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

final suspend - final awaitable

1 struct final_awaitable2 {3 bool await_ready() { return false;};4 void await_resume() noexcept{}56 template <typename P>7 coroutine_handle<> await_suspend(coroutine_handle<P> finalizedCoro)8 {9 return finalizedCoro.promise().continuation_;

10 }11 };

implementing task coroutine grzebiel 21.11.2019 53 / 61

Page 279: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

final suspend - final awaitable

1 struct final_awaitable2 {3 bool await_ready() { return false;};4 void await_resume() noexcept{}56 template <typename P>7 coroutine_handle<> await_suspend(coroutine_handle<P> finalizedCoro)8 {9 return finalizedCoro.promise().continuation_;

10 }11 };

implementing task coroutine grzebiel 21.11.2019 53 / 61

Page 280: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

final suspend - final awaitable

1 struct final_awaitable2 {3 bool await_ready ( ) { return false ;};4 void await_resume( ) noexcept{}56 template <typename P>7 coroutine_handle<> await_suspend(coroutine_handle<P> finalizedCoro )8 {9 return finalizedCoro.promise().continuation_;

10 }11 };

implementing task coroutine grzebiel 21.11.2019 53 / 61

Page 281: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

final suspend - final awaitable

1 struct final_awaitable2 {3 bool await_ready ( ) { return false ;};4 void await_resume( ) noexcept{}56 template <typename P>7 coroutine_handle<> await_suspend(coroutine_handle<P> finalizedCoro )8 {9 auto& continuation = finalizedCoro.promise().continuation_;

10 return continuation ? continuation : noop_coroutine;11 }12 };

implementing task coroutine grzebiel 21.11.2019 53 / 61

Page 282: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

final suspend - final awaitable

1 struct final_awaitable2 {3 bool await_ready ( ) { return false ;};4 void await_resume( ) noexcept{}56 template <typename P>7 coroutine_handle<> await_suspend(coroutine_handle<P> finalizedCoro )8 {9 auto& continuation = finalizedCoro.promise().continuation_;

10 return continuation ? continuation : noop_coroutine;11 }12 };

implementing task coroutine grzebiel 21.11.2019 53 / 61

Page 283: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

final suspend - final awaitable

1 struct final_awaitable2 {3 bool await_ready ( ) { return false ;};4 void await_resume( ) noexcept{}56 template <typename P>7 coroutine_handle<> await_suspend(coroutine_handle<P> finalizedCoro )8 {9 auto& continuation = finalizedCoro.promise().continuation_;

10 return continuation ? continuation : noop_coroutine;11 }12 };

implementing task coroutine grzebiel 21.11.2019 53 / 61

Page 284: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

take away

implementing task coroutine grzebiel 21.11.2019 54 / 61

Page 285: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

take away

• coroutine are flexible

implementing task coroutine grzebiel 21.11.2019 54 / 61

Page 286: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

take away

• coroutine are flexible

• very flexible

implementing task coroutine grzebiel 21.11.2019 54 / 61

Page 287: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

take away

• coroutine are flexible

• very flexible

• so flexible

implementing task coroutine grzebiel 21.11.2019 54 / 61

Page 288: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

take away

• coroutine are flexible

• very flexible

• so flexible

• with customization point

implementing task coroutine grzebiel 21.11.2019 54 / 61

Page 289: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

take away

• coroutine are flexible

• very flexible

• so flexible

• with customization point

• and more customization points

implementing task coroutine grzebiel 21.11.2019 54 / 61

Page 290: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

end of

slides removed from live presentation

implementing task coroutine grzebiel 21.11.2019 55 / 61

Page 291: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

confesion

implementing task coroutine grzebiel 21.11.2019 56 / 61

Page 292: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

confesion

implementing task coroutine grzebiel 21.11.2019 56 / 61

Page 293: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

back to motivation

implementing task coroutine grzebiel 21.11.2019 57 / 61

Page 294: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

back to motivation

1 using namespace async;2 void perform_experiment(experiment const& ex, session& s) {3 std::vector<std::future<sample_result>> worker_futures;4 for(auto const& s: ex.samples)5 worker_futures.push_back(worker.analyze(s));67 std::vector<sample_result> results;8 for (auto& f : worker_futures)9 results.push_back(f.get());

10 s.respond(results).get();11 };

implementing task coroutine grzebiel 21.11.2019 58 / 61

Page 295: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

back to motivation

1 using namespace coro;2 eager_task<void> perform_experiment(experiment ex , session& s) {3 std : : vector<eager_task<sample_result>> worker_tasks ;4 for (auto& s : ex . samples)5 worker_tasks .emplace_back(worker . analyze (s ) ) ;67 std : : vector<sample_result> results ;8 for (auto& f : worker_tasks )9 results .push_back(co_await f ) ;

10 co_await s . respond( results ) ;11 };

implementing task coroutine grzebiel 21.11.2019 58 / 61

Page 296: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

back to motivation

1 using namespace coro;2 eager_task<void> perform_experiment(experiment ex, session& s) {3 std : : vector<eager_task<sample_result>> worker_tasks ;4 for (auto& s : ex . samples)5 worker_tasks .emplace_back(worker . analyze (s ) ) ;67 std : : vector<sample_result> results ;8 for (auto& f : worker_tasks )9 results .push_back(co_await f ) ;

10 co_await s . respond( results ) ;11 };

implementing task coroutine grzebiel 21.11.2019 58 / 61

Page 297: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

back to motivation

1 using namespace coro;2 eager_task<void> perform_experiment(experiment ex, session& s) {3 std::vector<eager_task<sample_result>> worker_tasks;4 for(auto& s: ex.samples)5 worker_tasks.emplace_back(worker.analyze(s));67 std : : vector<sample_result> results ;8 for (auto& f : worker_tasks )9 results .push_back(co_await f ) ;

10 co_await s . respond( results ) ;11 };

implementing task coroutine grzebiel 21.11.2019 58 / 61

Page 298: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

back to motivation

1 using namespace coro;2 eager_task<void> perform_experiment(experiment ex, session& s) {3 std::vector<eager_task<sample_result>> worker_tasks;4 for(auto& s: ex.samples)5 worker_tasks.emplace_back(worker.analyze(s));67 std::vector<sample_result> results;8 for (auto& f : worker_tasks )9 results .push_back(co_await f ) ;

10 co_await s . respond( results ) ;11 };

implementing task coroutine grzebiel 21.11.2019 58 / 61

Page 299: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

back to motivation

1 using namespace coro;2 eager_task<void> perform_experiment(experiment ex, session& s) {3 std::vector<eager_task<sample_result>> worker_tasks;4 for(auto& s: ex.samples)5 worker_tasks.emplace_back(worker.analyze(s));67 std::vector<sample_result> results;8 for (auto& f : worker_tasks)9 results.push_back(co_await f);

10 co_await s . respond( results ) ;11 };

implementing task coroutine grzebiel 21.11.2019 58 / 61

Page 300: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

back to motivation

1 using namespace coro;2 eager_task<void> perform_experiment(experiment ex, session& s) {3 std::vector<eager_task<sample_result>> worker_tasks;4 for(auto& s: ex.samples)5 worker_tasks.emplace_back(worker.analyze(s));67 std::vector<sample_result> results;8 for (auto& f : worker_tasks)9 results.push_back(co_await f);

10 co_await s.respond(results);11 };

implementing task coroutine grzebiel 21.11.2019 58 / 61

Page 301: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

any asynchronous code

implementing task coroutine grzebiel 21.11.2019 59 / 61

Page 302: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

any asynchronous code

• I/O access

implementing task coroutine grzebiel 21.11.2019 59 / 61

Page 303: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

any asynchronous code

• I/O access

• networking

implementing task coroutine grzebiel 21.11.2019 59 / 61

Page 304: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

any asynchronous code

• I/O access

• networking

• disks

implementing task coroutine grzebiel 21.11.2019 59 / 61

Page 305: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

any asynchronous code

• I/O access

• networking

• disks

• inter process communication

implementing task coroutine grzebiel 21.11.2019 59 / 61

Page 306: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

any asynchronous code

• I/O access

• networking

• disks

• inter process communication

• data bases

implementing task coroutine grzebiel 21.11.2019 59 / 61

Page 307: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

abusing!

implementing task coroutine grzebiel 21.11.2019 60 / 61

Page 308: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

abusing!

• sick optimization techniques

implementing task coroutine grzebiel 21.11.2019 60 / 61

Page 309: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

abusing!

• sick optimization techniques

• data structures!

implementing task coroutine grzebiel 21.11.2019 60 / 61

Page 310: C++20 Coroutines - Introduction · 2019-11-25 · C++20 Coroutines Introduction Marcin Grzebieluch grzebieluch@me.com 21.11.2019 grzebiel 21.11.2019 2 / 61

?implementing task coroutine grzebiel 21.11.2019 61 / 61