Skip to content

Instantly share code, notes, and snippets.

@terrywh
Last active February 26, 2020 11:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save terrywh/c4be8d75652155a3bf3964963574134b to your computer and use it in GitHub Desktop.
Save terrywh/c4be8d75652155a3bf3964963574134b to your computer and use it in GitHub Desktop.
Coroutine TS DEMO https://godbolt.org/z/b9PFF8
#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