Skip to content

Instantly share code, notes, and snippets.

@HungMingWu
Last active April 27, 2018 07:39
Show Gist options
  • Select an option

  • Save HungMingWu/6e89ff95fa13599eb9bcb51e3b1d5510 to your computer and use it in GitHub Desktop.

Select an option

Save HungMingWu/6e89ff95fa13599eb9bcb51e3b1d5510 to your computer and use it in GitHub Desktop.
Coroutine Example
#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