Skip to content

Instantly share code, notes, and snippets.

@jupp0r
Last active June 1, 2018 01:19
Show Gist options
  • Save jupp0r/a4d624f8738aaafc50887de3e2e5ce97 to your computer and use it in GitHub Desktop.
Save jupp0r/a4d624f8738aaafc50887de3e2e5ce97 to your computer and use it in GitHub Desktop.
Minimal coroutines-ts generator
// compile with clang++ -g -std=c++17 -fcoroutines-ts coro.cpp
#include <experimental/coroutine>
#include <iostream>
struct generator {
struct promise_type {
int current_value;
auto initial_suspend() { return std::experimental::suspend_always{}; }
auto final_suspend() { return std::experimental::suspend_always{}; }
auto yield_value(int value) {
current_value = value;
return std::experimental::suspend_always{};
}
auto get_return_object() {
return generator{handle_type::from_promise(*this)};
}
auto return_void() { return std::experimental::suspend_always{}; }
static void unhandled_exception() { std::exit(1); }
};
using handle_type = std::experimental::coroutine_handle<promise_type>;
auto await_ready() { return false; }
auto await_resume() {
const auto r = coro.promise().current_value;
return r;
}
void await_suspend(std::experimental::coroutine_handle<> awaiting) {
coro.resume();
awaiting.resume();
}
generator(handle_type h) : coro(h) {}
handle_type coro;
struct iterator : public std::iterator<std::input_iterator_tag, int> {
std::experimental::coroutine_handle<promise_type> coro;
iterator() = default;
iterator(std::experimental::coroutine_handle<promise_type> coroutine)
: coro(coroutine) {}
iterator &operator++() {
coro.resume();
if (coro.done()) {
coro = nullptr;
}
return *this;
}
int operator*() { return coro.promise().current_value; }
bool operator!=(const iterator &other) const {
return (coro != other.coro);
}
auto await_ready() { return false; }
void await_suspend(std::experimental::coroutine_handle<> awaiting) {
awaiting.resume();
}
auto await_resume() { return *this; }
};
iterator begin() {
if (coro) {
coro.resume();
if (coro.done()) {
return end();
}
}
return iterator{coro};
}
iterator end() { return iterator{}; }
int *getNext() {
coro.resume();
if (coro.done()) {
return nullptr;
}
return &coro.promise().current_value;
}
};
generator gen(int max) {
for (int i = 0; i < max; i++) {
co_yield i;
}
}
generator run() {
auto g = gen(100);
std::cout << "regular co_await: " << co_await g << std::endl;
for
co_await(auto x : g) {
std::cout << "range-based co_await: " << x << std::endl;
}
}
int main(int argc, char **argv) { run().getNext(); }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment