Last active
June 1, 2018 01:19
-
-
Save jupp0r/a4d624f8738aaafc50887de3e2e5ce97 to your computer and use it in GitHub Desktop.
Minimal coroutines-ts generator
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
// 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