Last active
February 26, 2020 11:11
-
-
Save terrywh/c4be8d75652155a3bf3964963574134b to your computer and use it in GitHub Desktop.
Coroutine TS DEMO https://godbolt.org/z/b9PFF8
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 <coroutine> | |
#include <exception> | |
#include <iostream> | |
template <typename ReturnType> | |
class Resumable; | |
template <typename ReturnType> | |
struct Awaitable; | |
template <typename ReturnType> | |
struct Promise; | |
template <typename ReturnType> | |
class Resumable { | |
public: | |
using promise_type = Promise<ReturnType>; | |
using coroutine_handle = std::coroutine_handle<promise_type>; | |
Resumable(coroutine_handle handle): handle_(handle) {} | |
void resume() { | |
handle_.resume(); | |
} | |
void resume(ReturnType rv) { | |
handle_.promise().value(rv); | |
handle_.resume(); | |
} | |
ReturnType value() { | |
return handle_.promise().value(); | |
} | |
bool is_done() { | |
return handle_.promise().value() == -1; | |
} | |
private: | |
coroutine_handle handle_; | |
}; | |
template <typename ReturnType> | |
struct Awaitable { | |
using promise_type = Promise<ReturnType>; | |
using coroutine_handle = std::coroutine_handle<promise_type>; | |
Awaitable(Promise<ReturnType>& promise): promise_(promise) {} | |
bool await_ready() { | |
return false; | |
} | |
void await_suspend(coroutine_handle& handle) {} | |
ReturnType await_resume() { | |
return promise_.rv_; | |
} | |
Promise<ReturnType>& promise_; | |
}; | |
template <typename ReturnType> | |
struct Promise { | |
using coroutine_handle = std::coroutine_handle<Promise>; | |
Resumable<ReturnType> get_return_object() { | |
std::cout << "-@-\n"; | |
return coroutine_handle::from_promise(*this); | |
} | |
// 初始调用不暂停 | |
auto initial_suspend() { | |
std::cout << "-|-\n"; | |
// return std::suspend_always(); | |
return std::suspend_never(); | |
} | |
// 结束调用不暂停 | |
auto final_suspend() { | |
std::cout << "-=-\n"; | |
// return std::suspend_always(); | |
rv_ = -1; | |
return std::suspend_never(); | |
} | |
void return_void() {} | |
auto return_value(ReturnType&& rv) { | |
return rv_; | |
} | |
auto yield_value(ReturnType&& rv) { | |
std::cout << "-<-" << std::endl; | |
rv_ = std::move(rv); | |
// return std::suspend_always(); | |
return Awaitable<ReturnType>(*this); | |
} | |
void unhandled_exception() { | |
std::terminate(); | |
} | |
ReturnType value() { | |
return std::move(rv_); | |
} | |
void value(ReturnType rv) { | |
rv_ = std::move(rv); | |
} | |
ReturnType rv_; | |
}; | |
// 定义实现一个协程 | |
Resumable<int> square(int x) { | |
while(x < 10) { | |
std::cout << "==> " << x << std::endl; | |
x = co_yield x * x; | |
if(x == 0) x = 1; | |
else if(x == 1) x = 2; | |
} | |
} | |
int main(int argc, char* argv[]) { | |
// 调用协程 | |
Resumable<int> r = square(0); | |
int x = 0; | |
while(!r.is_done()) { | |
std::cout << "<== " << r.value() << std::endl; | |
r.resume(++x); | |
} | |
std::cout << "<== " << r.value() << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment