Created
April 27, 2018 08:51
-
-
Save HungMingWu/709e9dd1bd067947dace53cada4cbf7c to your computer and use it in GitHub Desktop.
This file contains 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); | |
} | |
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;; | |
auto operator co_await() { | |
struct awaitable_type { | |
handle_type coro; | |
bool await_ready() { | |
const auto ready = coro.done(); | |
std::cout << "Await " << (ready ? "is ready" : "isn't ready") << std::endl; | |
return coro.done(); | |
} | |
#ifdef _WIN32 | |
void await_suspend(std::experimental::coroutine_handle<> awaiting) { | |
std::cout << "Got to resume the lazy" << std::endl; | |
coro.resume(); | |
std::cout << "Got to resume the awaiter" << std::endl; | |
awaiting.resume(); | |
} | |
#else | |
auto await_suspend(std::experimental::coroutine_handle<> awaiting) { | |
std::cout << "About to resume the lazy" << std::endl; | |
coro.resume(); | |
std::cout << "Returning awaiting coroutine as a continuation" << std::endl; | |
return awaiting; | |
} | |
#endif | |
auto await_resume() { | |
const auto r = coro.promise().value; | |
std::cout << "Await value is returned: " << r << std::endl; | |
return r; | |
} | |
}; | |
return awaitable_type{ this->coro }; | |
} | |
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; | |
} | |
sync<int> await_answer() { | |
std::cout << "Started await_answer" << std::endl; | |
auto a = answer(); | |
std::cout << "Got a coroutine, let's get a value" << std::endl; | |
auto v = co_await a; | |
std::cout << "And the coroutine value is: " << v << std::endl; | |
v = co_await a; | |
std::cout << "And the coroutine value is still: " << v << std::endl; | |
co_return 0; | |
} | |
int main() { | |
return await_answer().get(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment