lang:cpp:coroutine
Ceci est une ancienne révision du document !
co_yield
Version Visual Studio :
#include <iostream> #include <experimental/generator> std::experimental::generator<int> loop(int iterations) { for (int i = 0; i < iterations; i++) { co_yield i; } } int main() { for (int i : loop(100)) { std::cout << i << std::endl; } }
Version gcc/clang :
#include <coroutine> #include <memory> #include <iostream> namespace coro_exp { template<typename T> class generator { public: struct promise_type; using handle_type = std::coroutine_handle<promise_type>; private: handle_type coro; public: explicit generator(handle_type h) : coro(h) {} generator(const generator &) = delete; generator(generator &&oth) noexcept : coro(oth.coro) { oth.coro = nullptr; } generator &operator=(const generator &) = delete; generator &operator=(generator &&other) noexcept { 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 { private: T current_value{}; friend class generator; public: promise_type() = default; ~promise_type() = default; promise_type(const promise_type&) = delete; promise_type(promise_type&&) = delete; promise_type &operator=(const promise_type&) = delete; promise_type &operator=(promise_type&&) = delete; auto initial_suspend() { return std::suspend_always{}; } auto final_suspend() { return std::suspend_always{}; } auto get_return_object() { return generator{handle_type::from_promise(*this)}; } auto return_void() { return std::suspend_never{}; } auto yield_value(T some_value) { current_value = some_value; return std::suspend_always{}; } void unhandled_exception() { std::exit(1); } }; }; } // coroutn_exp using coro_exp::generator; static constexpr int demo_ceiling = 100; generator<int> loop(int iterations) { 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 << '\n'; } }
co_return et co_await
#include <future> #include <iostream> std::future<int> t() { return std::async([]() { std::cout << "I" << std::endl; return 1; }); } std::future<void> foobar() { std::cout << " First call !\n"; std::cout << " Ret " << co_await t() << std::endl; std::cout << " Still first call !\n"; std::cout << " Ret2 " << co_await t() << std::endl; std::cout << " Only after resumed !\n"; } void tt() { auto ttt = foobar(); for (int i = 0; i < 10; i ++) std::cout << i << std::endl; for (int i = 0; i < 100; i++) std::this_thread::sleep_for(std::chrono::milliseconds(10)); ttt.wait(); } int main() { tt(); }
Retour possible :
First call ! Ret I 0 1 2 1 Still first call ! Ret2 3 4 5 6 7 8 9 I 1 Only after resumed !
lang/cpp/coroutine.1585232390.txt.gz · Dernière modification : 2020/03/26 15:19 de root