lang:cpp:coroutine
Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
lang:cpp:coroutine [2019/11/15 13:19] – Mise à jour de "await" avec une valeur de retour à std::future root | lang:cpp:coroutine [2023/04/27 05:05] (Version actuelle) – Ajout de "Gajendra Gulgulia" root | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | ===co_await=== | + | ====Exemples==== |
+ | ===co_yield=== | ||
+ | Version Visual Studio : | ||
<code cpp> | <code cpp> | ||
#include < | #include < | ||
Ligne 19: | Ligne 21: | ||
} | } | ||
} | } | ||
+ | </ | ||
+ | |||
+ | Version gcc/clang : | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | namespace coro_exp { | ||
+ | |||
+ | template< | ||
+ | class generator { | ||
+ | | ||
+ | struct promise_type; | ||
+ | using handle_type = std:: | ||
+ | | ||
+ | handle_type coro; | ||
+ | | ||
+ | explicit generator(handle_type h) : coro(h) {} | ||
+ | generator(const generator &) = delete; | ||
+ | generator(generator && | ||
+ | oth.coro = nullptr; | ||
+ | } | ||
+ | generator & | ||
+ | generator & | ||
+ | coro = other.coro; | ||
+ | other.coro = nullptr; | ||
+ | return *this; | ||
+ | } | ||
+ | ~generator() { | ||
+ | if (coro) { | ||
+ | coro.destroy(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | bool next() { | ||
+ | coro.resume(); | ||
+ | return not coro.done(); | ||
+ | } | ||
+ | |||
+ | T getValue() { | ||
+ | return coro.promise().current_value; | ||
+ | } | ||
+ | |||
+ | struct promise_type { | ||
+ | | ||
+ | T current_value{}; | ||
+ | friend class generator; | ||
+ | | ||
+ | promise_type() = default; | ||
+ | ~promise_type() = default; | ||
+ | promise_type(const promise_type& | ||
+ | promise_type(promise_type&& | ||
+ | promise_type & | ||
+ | promise_type & | ||
+ | |||
+ | auto initial_suspend() { | ||
+ | return std:: | ||
+ | } | ||
+ | |||
+ | auto final_suspend() { | ||
+ | return std:: | ||
+ | } | ||
+ | |||
+ | auto get_return_object() { | ||
+ | return generator{handle_type:: | ||
+ | } | ||
+ | |||
+ | auto return_void() { | ||
+ | return std:: | ||
+ | } | ||
+ | |||
+ | auto yield_value(T some_value) { | ||
+ | current_value = some_value; | ||
+ | return std:: | ||
+ | } | ||
+ | |||
+ | void unhandled_exception() { | ||
+ | std:: | ||
+ | } | ||
+ | }; | ||
+ | }; | ||
+ | |||
+ | } // coroutn_exp | ||
+ | |||
+ | using coro_exp:: | ||
+ | |||
+ | static constexpr int demo_ceiling = 100; | ||
+ | |||
+ | generator< | ||
+ | { | ||
+ | for (int i = 0; i < iterations; i++) | ||
+ | { | ||
+ | co_yield i; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | int main() { | ||
+ | auto iter = loop(demo_ceiling); | ||
+ | while(iter.next()) { | ||
+ | const auto value = iter.getValue(); | ||
+ | std::cout << value << ' | ||
+ | } | ||
+ | } | ||
+ | |||
</ | </ | ||
Ligne 76: | Ligne 185: | ||
Only after resumed ! | Only after resumed ! | ||
</ | </ | ||
+ | |||
+ | ====Tutorial==== | ||
+ | |||
+ | ===Gajendra Gulgulia=== | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | * Partie 4 | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | //global counter | ||
+ | int num{0}; | ||
+ | |||
+ | struct ReturnObject{ | ||
+ | struct promise_type{ | ||
+ | | ||
+ | promise_type(){std:: | ||
+ | |||
+ | ReturnObject get_return_object() { | ||
+ | std::cout << | ||
+ | return {}; | ||
+ | } | ||
+ | |||
+ | std:: | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | std:: | ||
+ | std::cout << | ||
+ | return {}; | ||
+ | } | ||
+ | | ||
+ | void unhandled_exception(){std:: | ||
+ | }; | ||
+ | }; | ||
+ | |||
+ | ReturnObject foo(){ | ||
+ | | ||
+ | std::cout << | ||
+ | co_await std:: | ||
+ | co_await std:: | ||
+ | co_await std:: | ||
+ | std::cout << | ||
+ | } | ||
+ | |||
+ | int main(){foo(); | ||
+ | std::cout << | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | * Partie 5 | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | static int ctr{0}; | ||
+ | |||
+ | struct ReturnObject { | ||
+ | struct promise_type { | ||
+ | ReturnObject get_return_object() { | ||
+ | // call ctor of ReturnObject with the coroutine handle | ||
+ | return { | ||
+ | std:: | ||
+ | } | ||
+ | std:: | ||
+ | std:: | ||
+ | void unhandled_exception() {} | ||
+ | }; | ||
+ | |||
+ | // B.3 implicit conversion operator | ||
+ | operator std:: | ||
+ | |||
+ | | ||
+ | std:: | ||
+ | |||
+ | ReturnObject(std:: | ||
+ | }; | ||
+ | |||
+ | // coroutine | ||
+ | ReturnObject foo() { | ||
+ | std::cout << ++ctr << ". hello from coroutine 1\n"; | ||
+ | co_await std:: | ||
+ | std::cout << ++ctr << ". hello from coroutine 2\n"; | ||
+ | co_await std:: | ||
+ | std::cout << ++ctr << ". hello from coroutine 3\n"; | ||
+ | } | ||
+ | |||
+ | // main | ||
+ | int main() { | ||
+ | std:: | ||
+ | std::cout << ++ctr << ". resuming coroutine from main 1\n"; | ||
+ | h(); | ||
+ | std::cout << ++ctr << ". resuming coroutine from main 2\n"; | ||
+ | h.resume(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | * Partie 6.2 | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | int ctr{0}; | ||
+ | |||
+ | struct suspend_always { | ||
+ | bool await_ready() const noexcept { | ||
+ | std::cout << ++ctr << ". suspend_always:: | ||
+ | return false; | ||
+ | } | ||
+ | void await_suspend(std:: | ||
+ | std::cout << ++ctr << ". suspend_always:: | ||
+ | } | ||
+ | void await_resume() const noexcept { | ||
+ | std::cout << ++ctr << ". suspend_always:: | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | // ReturnObject same as in section 5 | ||
+ | struct ReturnObject { | ||
+ | struct promise_type { | ||
+ | unsigned value_{0}; | ||
+ | ReturnObject get_return_object() { | ||
+ | return {std:: | ||
+ | } | ||
+ | std:: | ||
+ | std:: | ||
+ | void unhandled_exception() {} | ||
+ | }; | ||
+ | |||
+ | std:: | ||
+ | ReturnObject(std:: | ||
+ | operator std:: | ||
+ | }; | ||
+ | |||
+ | ReturnObject foo() { | ||
+ | std::cout << ++ctr << ". first hello from coroutine\n"; | ||
+ | |||
+ | co_await suspend_always{}; | ||
+ | |||
+ | std::cout << ++ctr << ". second hello from coroutine\n"; | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | std:: | ||
+ | std::cout << ++ctr << ". main\n"; | ||
+ | h(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | * Partie 6.3 | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | int ctr{0}; | ||
+ | |||
+ | struct suspend_always { | ||
+ | bool await_ready() const noexcept { | ||
+ | std::cout << ++ctr << ". suspend_always:: | ||
+ | return false; | ||
+ | } | ||
+ | |||
+ | bool await_suspend(std:: | ||
+ | std::cout << ++ctr << ". suspend_always:: | ||
+ | return true; // Change it. | ||
+ | } | ||
+ | void await_resume() const noexcept { | ||
+ | std::cout << ++ctr << ". suspend_always:: | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | struct ReturnObject { | ||
+ | struct promise_type { | ||
+ | unsigned value_{0}; | ||
+ | ReturnObject get_return_object() { | ||
+ | return {std:: | ||
+ | } | ||
+ | std:: | ||
+ | std:: | ||
+ | void unhandled_exception() {} | ||
+ | }; | ||
+ | |||
+ | std:: | ||
+ | ReturnObject(std:: | ||
+ | operator std:: | ||
+ | }; | ||
+ | |||
+ | ReturnObject foo() { | ||
+ | std::cout << ++ctr << ". first hello from coroutine\n"; | ||
+ | co_await suspend_always{}; | ||
+ | std::cout << ++ctr << ". second hello from coroutine\n"; | ||
+ | co_await std:: | ||
+ | std::cout << ++ctr << ". third hello from coroutine\n"; | ||
+ | } | ||
+ | |||
+ | int main() { std:: | ||
+ | </ | ||
+ | |||
+ | |||
+ | * Partie 6.4 | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | int ctr{0}; | ||
+ | |||
+ | // ReturnObject same as in section 5 | ||
+ | struct ReturnObject { | ||
+ | struct promise_type { | ||
+ | unsigned value_{0}; | ||
+ | ReturnObject get_return_object() { | ||
+ | return {std:: | ||
+ | } | ||
+ | std:: | ||
+ | std::cout << ++ctr << ". promise_type:: | ||
+ | return {}; | ||
+ | } | ||
+ | std:: | ||
+ | void unhandled_exception() {} | ||
+ | }; | ||
+ | |||
+ | std:: | ||
+ | ReturnObject(std:: | ||
+ | operator std:: | ||
+ | }; | ||
+ | |||
+ | struct suspend_always { | ||
+ | bool await_ready() const noexcept { | ||
+ | std::cout << ++ctr << ". suspend_always:: | ||
+ | return false; | ||
+ | } | ||
+ | void await_suspend( | ||
+ | std:: | ||
+ | std::cout << ++ctr << ". suspend_always:: | ||
+ | } | ||
+ | void await_resume() const noexcept { | ||
+ | std::cout << ++ctr << ". suspend_always:: | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | ReturnObject foo() { | ||
+ | std::cout << ++ctr << ". first hello from coroutine\n"; | ||
+ | |||
+ | co_await suspend_always{}; | ||
+ | |||
+ | std::cout << ++ctr << ". second hello from coroutine\n"; | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | std:: | ||
+ | std::cout << ++ctr << ". resuming coroutinefrom main\n"; | ||
+ | h(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | * Partie 6.5 | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | int ctr{0}; | ||
+ | |||
+ | template < | ||
+ | struct suspend_always { | ||
+ | bool await_ready() const noexcept { | ||
+ | std::cout << ++ctr << ". suspend_always:: | ||
+ | return false; | ||
+ | } | ||
+ | / | ||
+ | void await_suspend(std:: | ||
+ | std::cout << ++ctr << ". suspend_always:: | ||
+ | } | ||
+ | void await_resume() const noexcept { | ||
+ | std::cout << ++ctr << ". suspend_always:: | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | // same as in section 5 | ||
+ | struct ReturnObject { | ||
+ | struct promise_type { | ||
+ | unsigned value_{0}; | ||
+ | ReturnObject get_return_object() { | ||
+ | return {std:: | ||
+ | } | ||
+ | std:: | ||
+ | std:: | ||
+ | void unhandled_exception() {} | ||
+ | }; | ||
+ | |||
+ | std:: | ||
+ | ReturnObject(std:: | ||
+ | operator std:: | ||
+ | }; | ||
+ | |||
+ | ReturnObject foo() { | ||
+ | std::cout << ++ctr << ". first hello from coroutine\n"; | ||
+ | co_await suspend_always<> | ||
+ | co_await suspend_always< | ||
+ | std::cout << ++ctr << ". second hello from coroutine\n"; | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | std:: | ||
+ | std::cout << ++ctr << ". resuming coroutine from main 1\n"; | ||
+ | h(); | ||
+ | std::cout << ++ctr << ". resuming coroutine from main 2\n"; | ||
+ | h(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | * Partie 7.1 | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | // custom suspend_never | ||
+ | struct suspend_never { | ||
+ | double* val_{new double(10.234)}; | ||
+ | bool await_ready() const noexcept { return true; } | ||
+ | void await_suspend(std:: | ||
+ | double* await_resume() const noexcept { return val_; } | ||
+ | }; | ||
+ | |||
+ | // ReturnObject | ||
+ | struct ReturnObject { | ||
+ | struct promise_type { | ||
+ | unsigned value_{0}; | ||
+ | ReturnObject get_return_object() { | ||
+ | return {std:: | ||
+ | } | ||
+ | std:: | ||
+ | std:: | ||
+ | void unhandled_exception() {} | ||
+ | }; | ||
+ | |||
+ | std:: | ||
+ | ReturnObject(std:: | ||
+ | operator std:: | ||
+ | }; | ||
+ | |||
+ | // coroutine | ||
+ | ReturnObject foo() { | ||
+ | // temporary suspend_never is destroyed after evaluation | ||
+ | auto val1 = co_await suspend_never{}; | ||
+ | std::cout << *val1 << " | ||
+ | |||
+ | *val1 = 20.234; | ||
+ | delete val1; | ||
+ | |||
+ | auto val2 = co_await suspend_never{}; | ||
+ | std::cout << *val2 << " | ||
+ | delete val2; | ||
+ | } | ||
+ | |||
+ | // main | ||
+ | int main() { std:: | ||
+ | </ | ||
+ | |||
+ | * Partie 7.2 | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | int ctr{0}; | ||
+ | |||
+ | template < | ||
+ | struct suspend_never { | ||
+ | PromiseType* promise_{nullptr}; | ||
+ | bool await_ready() const noexcept { return false; } | ||
+ | |||
+ | void await_suspend(std:: | ||
+ | promise_ = & | ||
+ | } | ||
+ | |||
+ | PromiseType* await_resume() const noexcept { return promise_; } // 2.c | ||
+ | }; | ||
+ | |||
+ | struct ReturnObject { | ||
+ | struct promise_type { | ||
+ | int val_{11}; / | ||
+ | ReturnObject get_return_object() { | ||
+ | return {std:: | ||
+ | } | ||
+ | std:: | ||
+ | std:: | ||
+ | void unhandled_exception() {} | ||
+ | }; | ||
+ | |||
+ | std:: | ||
+ | ReturnObject(std:: | ||
+ | operator std:: | ||
+ | }; | ||
+ | |||
+ | ReturnObject foo() { | ||
+ | auto promise = | ||
+ | co_await suspend_never< | ||
+ | std::cout << promise-> | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | std:: | ||
+ | h(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | * Partie 7.3 | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | int ctr{0}; | ||
+ | |||
+ | template < | ||
+ | struct suspend_never { | ||
+ | PromiseType* promise_{nullptr}; | ||
+ | bool await_ready() const noexcept { return false; } | ||
+ | |||
+ | void await_suspend(std:: | ||
+ | promise_ = & | ||
+ | } | ||
+ | |||
+ | PromiseType* await_resume() const noexcept { return promise_; } // 2.c | ||
+ | }; | ||
+ | |||
+ | struct ReturnObject { | ||
+ | struct promise_type { | ||
+ | int val_{11}; / | ||
+ | ReturnObject get_return_object() { | ||
+ | return {std:: | ||
+ | } | ||
+ | std:: | ||
+ | std:: | ||
+ | void unhandled_exception() {} | ||
+ | }; | ||
+ | |||
+ | std:: | ||
+ | ReturnObject(std:: | ||
+ | operator std:: | ||
+ | }; | ||
+ | |||
+ | ReturnObject foo() { | ||
+ | auto promise = | ||
+ | co_await suspend_never< | ||
+ | std::cout << "From coroutine " << promise-> | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | std:: | ||
+ | ReturnObject:: | ||
+ | std::cout << "From main: " << prom.val_ << " | ||
+ | h(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | * Partie 7.4 | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | int ctr{0}; | ||
+ | template < | ||
+ | struct suspend_never { | ||
+ | PromiseType* promise_{nullptr}; | ||
+ | bool await_ready() const noexcept { return false; } // | ||
+ | |||
+ | bool await_suspend(std:: | ||
+ | promise_ = & | ||
+ | |||
+ | std::cout << ctr++ << ". In suspend_always:: | ||
+ | << " | ||
+ | << promise_-> | ||
+ | |||
+ | return false; | ||
+ | } | ||
+ | |||
+ | PromiseType* await_resume() const noexcept { return promise_; } | ||
+ | }; | ||
+ | |||
+ | struct ReturnObject { | ||
+ | struct promise_type { | ||
+ | int val_; | ||
+ | ReturnObject get_return_object() { | ||
+ | return {std:: | ||
+ | } | ||
+ | std:: | ||
+ | std:: | ||
+ | void unhandled_exception() {} | ||
+ | }; | ||
+ | |||
+ | std:: | ||
+ | ReturnObject(std:: | ||
+ | operator std:: | ||
+ | }; | ||
+ | |||
+ | using PromType = ReturnObject:: | ||
+ | |||
+ | ReturnObject foo() { | ||
+ | std::cout | ||
+ | << ctr++ | ||
+ | << ". Suspending the coroutine for 1st time with trivial awaitable\n"; | ||
+ | co_await std:: | ||
+ | |||
+ | std::cout | ||
+ | << ctr++ | ||
+ | << ". Suspending the coroutine for 2nd time with custom awaitable\n"; | ||
+ | auto promise = co_await suspend_never< | ||
+ | std::cout << ctr++ << ". Coroutine finished\n"; | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | std:: | ||
+ | PromType* prom = & | ||
+ | |||
+ | std::cout << ctr++ | ||
+ | << ". From main: current value of promise_-> | ||
+ | << " | ||
+ | std::cout << ctr++ | ||
+ | << ". Changing | ||
+ | |||
+ | prom-> | ||
+ | h(); | ||
+ | |||
+ | std::cout << ctr++ << ". main finished\n"; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | * Partie 8 | ||
+ | |||
+ | KO : | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | int ctr{0}; | ||
+ | |||
+ | template < | ||
+ | struct suspend_always { | ||
+ | PromiseType* promise_{nullptr}; | ||
+ | bool await_ready() const noexcept { return false; } | ||
+ | |||
+ | void await_suspend(std:: | ||
+ | promise_ = & | ||
+ | } | ||
+ | |||
+ | PromiseType* await_resume() const noexcept { return promise_; } // 2.c | ||
+ | }; | ||
+ | |||
+ | struct ReturnObject { | ||
+ | struct promise_type { | ||
+ | int val_; / | ||
+ | ReturnObject get_return_object() { | ||
+ | return {std:: | ||
+ | } | ||
+ | std:: | ||
+ | std:: | ||
+ | void unhandled_exception() {} | ||
+ | }; | ||
+ | |||
+ | std:: | ||
+ | ReturnObject(std:: | ||
+ | operator std:: | ||
+ | }; | ||
+ | |||
+ | using PromType = ReturnObject:: | ||
+ | ReturnObject generator() { | ||
+ | auto promise = co_await suspend_always< | ||
+ | for (int i = 0;; i++) { | ||
+ | promise-> | ||
+ | co_await std:: | ||
+ | } | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | std:: | ||
+ | PromType& | ||
+ | for (int i = 0; i < 5; ++i) { | ||
+ | std::cout << "From main: " << prom.val_ << " | ||
+ | h(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | OK : | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | template < | ||
+ | struct suspend_never { | ||
+ | PromiseType* promise_{nullptr}; | ||
+ | bool await_ready() const noexcept { return false; } | ||
+ | |||
+ | bool await_suspend(std:: | ||
+ | promise_ = & | ||
+ | return false; | ||
+ | } | ||
+ | |||
+ | PromiseType* await_resume() const noexcept { return promise_; } | ||
+ | }; | ||
+ | |||
+ | struct ReturnObject { | ||
+ | struct promise_type { | ||
+ | int val_; | ||
+ | ReturnObject get_return_object() { | ||
+ | return {std:: | ||
+ | } | ||
+ | std:: | ||
+ | std:: | ||
+ | void unhandled_exception() {} | ||
+ | }; | ||
+ | |||
+ | std:: | ||
+ | ReturnObject(std:: | ||
+ | operator std:: | ||
+ | }; | ||
+ | |||
+ | using PromType = ReturnObject:: | ||
+ | |||
+ | ReturnObject generator() { | ||
+ | auto promise = co_await suspend_never< | ||
+ | for (int i = 0;; i++) { | ||
+ | promise-> | ||
+ | co_await std:: | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ReturnObject evenNumberGenerator() { | ||
+ | auto promise = co_await suspend_never< | ||
+ | for (int i = 0;; i = i + 2) { | ||
+ | promise-> | ||
+ | co_await std:: | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ReturnObject oddNumberGenerator() { | ||
+ | auto promise = co_await suspend_never< | ||
+ | for (int i = 1;; i = i + 2) { | ||
+ | promise-> | ||
+ | co_await std:: | ||
+ | } | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | std:: | ||
+ | PromType& | ||
+ | for (int i = 0; i < 5; ++i) { | ||
+ | std::cout << "From main: " << prom.val_ << " | ||
+ | h(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | [[https:// | ||
+ | }} | ||
+ | * Partie 9 | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | struct ReturnObject { | ||
+ | struct promise_type { | ||
+ | int val_; | ||
+ | ReturnObject get_return_object() { | ||
+ | return {std:: | ||
+ | } | ||
+ | std:: | ||
+ | std:: | ||
+ | std:: | ||
+ | val_ = value; | ||
+ | return {}; | ||
+ | } | ||
+ | void unhandled_exception() {} | ||
+ | }; | ||
+ | |||
+ | std:: | ||
+ | ReturnObject(std:: | ||
+ | operator std:: | ||
+ | }; | ||
+ | |||
+ | using PromType = ReturnObject:: | ||
+ | |||
+ | ReturnObject generator() { | ||
+ | for (int i = 0;; i++) { | ||
+ | co_yield i; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | std:: | ||
+ | PromType& | ||
+ | for (int i = 0; i < 5; ++i) { | ||
+ | std::cout << "From main: " << prom.val_ << " | ||
+ | h(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ReturnObject evenNumberGenerator() { | ||
+ | for (int i = 0;; i = i + 2) { | ||
+ | co_yield i; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ReturnObject oddNumberGenerator() { | ||
+ | for (int i = 1;; i = i + 2) { | ||
+ | co_yield i; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | * Partie 10 | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | template < | ||
+ | struct ReturnObject { | ||
+ | struct promise_type { | ||
+ | T val_; | ||
+ | ReturnObject get_return_object() { | ||
+ | return {std:: | ||
+ | } | ||
+ | std:: | ||
+ | std:: | ||
+ | std:: | ||
+ | val_ = value; | ||
+ | return {}; | ||
+ | } | ||
+ | void unhandled_exception() {} | ||
+ | }; | ||
+ | |||
+ | std:: | ||
+ | ReturnObject(std:: | ||
+ | operator std:: | ||
+ | }; | ||
+ | |||
+ | using PromType = ReturnObject< | ||
+ | |||
+ | template < | ||
+ | ReturnObject< | ||
+ | for (int i = 0;; i++) { | ||
+ | co_yield 1.234 + static_cast< | ||
+ | } | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | std:: | ||
+ | PromType& | ||
+ | for (int i = 0; i < 5; ++i) { | ||
+ | std::cout << "From main: " << prom.val_ << " | ||
+ | h(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | * Partie 11.1 | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | struct ReturnObject { | ||
+ | struct promise_type { | ||
+ | int val_{23}; | ||
+ | ReturnObject get_return_object() { | ||
+ | return {std:: | ||
+ | } | ||
+ | std:: | ||
+ | std:: | ||
+ | void unhandled_exception() {} | ||
+ | void return_void() {} | ||
+ | }; | ||
+ | |||
+ | std:: | ||
+ | ReturnObject(std:: | ||
+ | operator std:: | ||
+ | }; | ||
+ | |||
+ | using PromType = ReturnObject:: | ||
+ | |||
+ | ReturnObject foo() { co_return; } | ||
+ | |||
+ | int main() { | ||
+ | std:: | ||
+ | std::cout << h.promise().val_ << " | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | * Partie 11.2 | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | struct ReturnObject { | ||
+ | struct promise_type { | ||
+ | int val_; | ||
+ | ReturnObject get_return_object() { | ||
+ | return {std:: | ||
+ | } | ||
+ | std:: | ||
+ | std:: | ||
+ | void unhandled_exception() {} | ||
+ | void return_value(int val) { val_ = val; } | ||
+ | }; | ||
+ | |||
+ | std:: | ||
+ | ReturnObject(std:: | ||
+ | operator std:: | ||
+ | }; | ||
+ | |||
+ | using PromType = ReturnObject:: | ||
+ | |||
+ | ReturnObject foo() { co_return 121; } | ||
+ | |||
+ | int main() { | ||
+ | std:: | ||
+ | std::cout << h.promise().val_ << " | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | * Partie 12 | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | struct ReturnObject { | ||
+ | struct promise_type { | ||
+ | int val_; | ||
+ | ReturnObject get_return_object() { | ||
+ | return {std:: | ||
+ | } | ||
+ | std:: | ||
+ | void return_void() { std::cout << " | ||
+ | std:: | ||
+ | void unhandled_exception() {} | ||
+ | }; | ||
+ | |||
+ | std:: | ||
+ | ReturnObject(std:: | ||
+ | operator std:: | ||
+ | }; | ||
+ | |||
+ | ReturnObject foo() { co_await std:: | ||
+ | int main() { foo(); } | ||
+ | </ | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | struct ReturnObject { | ||
+ | struct promise_type { | ||
+ | int val_; | ||
+ | ReturnObject get_return_object() { | ||
+ | return {std:: | ||
+ | } | ||
+ | std:: | ||
+ | |||
+ | std:: | ||
+ | std::cout << " | ||
+ | return {}; | ||
+ | } | ||
+ | void unhandled_exception() {} | ||
+ | |||
+ | void return_void() { std::cout << " | ||
+ | }; | ||
+ | |||
+ | std:: | ||
+ | ReturnObject(std:: | ||
+ | operator std:: | ||
+ | }; | ||
+ | |||
+ | using PromType = ReturnObject:: | ||
+ | |||
+ | ReturnObject foo() { co_await std:: | ||
+ | |||
+ | int main() { | ||
+ | std:: | ||
+ | PromType* prom = & | ||
+ | /* | ||
+ | call h.resume() many times | ||
+ | */ | ||
+ | if (h.done()) { | ||
+ | /* | ||
+ | do something with prom one last time | ||
+ | */ | ||
+ | std::cout << "done execution of coroutine\n"; | ||
+ | h.destroy(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ |
lang/cpp/coroutine.1573820387.txt.gz · Dernière modification : 2019/11/15 13:19 de root