Last active
April 27, 2018 07:39
-
-
Save HungMingWu/6e89ff95fa13599eb9bcb51e3b1d5510 to your computer and use it in GitHub Desktop.
Coroutine Example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <type_traits> | |
| #include <iostream> | |
| #include <experimental/coroutine> | |
| template<typename T> | |
| struct coreturn { | |
| struct promise; | |
| friend struct promise; | |
| using handle_type = std::experimental::coroutine_handle<promise>; | |
| coreturn(const coreturn &) = delete; | |
| coreturn(coreturn &&s) | |
| : coro(s.coro) { | |
| std::cout << "Coreturn wrapper moved" << std::endl; | |
| s.coro = nullptr; | |
| } | |
| ~coreturn() { | |
| std::cout << "Coreturn wrapper gone" << std::endl; | |
| if (coro) coro.destroy(); | |
| } | |
| coreturn &operator = (const coreturn &) = delete; | |
| coreturn &operator = (coreturn &&s) { | |
| coro = s.coro; | |
| s.coro = nullptr; | |
| return *this; | |
| } | |
| struct promise { | |
| friend struct coreturn; | |
| promise() { | |
| std::cout << "Promise created" << std::endl; | |
| } | |
| ~promise() { | |
| std::cout << "Promise died" << std::endl; | |
| } | |
| auto return_value(T v) { | |
| std::cout << "Got an answer of " << v << std::endl; | |
| value = v; | |
| return std::experimental::suspend_never{}; | |
| } | |
| auto final_suspend() { | |
| std::cout << "Finished the coro" << std::endl; | |
| return std::experimental::suspend_always{}; | |
| } | |
| void unhandled_exception() { | |
| std::exit(1); | |
| } | |
| private: | |
| T value; | |
| }; | |
| protected: | |
| T get() { | |
| return coro.promise().value; | |
| } | |
| coreturn(handle_type h) | |
| : coro(h) { | |
| std::cout << "Created a coreturn wrapper object" << std::endl; | |
| } | |
| handle_type coro; | |
| }; | |
| template<typename T> | |
| struct sync : public coreturn<T> { | |
| using coreturn<T>::coreturn; | |
| using handle_type = typename coreturn<T>::handle_type; | |
| T get() { | |
| std::cout << "We got asked for the return value..." << std::endl; | |
| return coreturn<T>::get(); | |
| } | |
| struct promise_type : public coreturn<T>::promise { | |
| auto get_return_object() { | |
| std::cout << "Send back a sync" << std::endl; | |
| return sync<T>{handle_type::from_promise(*this)}; | |
| } | |
| auto initial_suspend() { | |
| std::cout << "Started the coroutine, don't stop now!" << std::endl; | |
| return std::experimental::suspend_never{}; | |
| } | |
| }; | |
| }; | |
| template<typename T> | |
| struct lazy : public coreturn<T> { | |
| using coreturn<T>::coreturn; | |
| using handle_type = typename coreturn<T>::handle_type;; | |
| T get() { | |
| std::cout << "We got asked for the return value..." << std::endl; | |
| if (!this->coro.done()) this->coro.resume(); | |
| return coreturn<T>::get(); | |
| } | |
| struct promise_type : public coreturn<T>::promise { | |
| auto get_return_object() { | |
| std::cout << "Send back a lazy" << std::endl; | |
| return lazy<T>{handle_type::from_promise(*this)}; | |
| } | |
| auto initial_suspend() { | |
| std::cout << "Started the coroutine, put the brakes on!" << std::endl; | |
| return std::experimental::suspend_always{}; | |
| } | |
| }; | |
| }; | |
| lazy<int> answer() { | |
| std::cout << "Thinking deep thoughts..." << std::endl; | |
| co_return 42; | |
| } | |
| int main() { | |
| std::cout << "coro1" << std::endl; | |
| auto a = answer(); | |
| std::cout << "Got a coroutine, let's get a value" << std::endl; | |
| auto v = a.get(); | |
| std::cout << "And the coroutine value is: " << v << std::endl; | |
| v = a.get(); | |
| std::cout << "And the coroutine value is still: " << v << std::endl; | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment