diff --git a/ostd/coroutine.hh b/ostd/coroutine.hh index 8a02810..98f45a4 100644 --- a/ostd/coroutine.hh +++ b/ostd/coroutine.hh @@ -14,9 +14,11 @@ #include #include #include +#include #include "ostd/types.hh" #include "ostd/platform.hh" +#include "ostd/range.hh" /* from boost.context */ #ifdef OSTD_PLATFORM_WIN32 @@ -101,7 +103,7 @@ struct coroutine_context { } void yield_jump() { - p_coro = detail::ostd_jump_fcontext(p_orig, nullptr).ctx; + p_orig = detail::ostd_jump_fcontext(p_orig, nullptr).ctx; } bool is_done() const { @@ -355,6 +357,47 @@ private: std::function &, A...)> p_func; }; +template +struct generator: input_range> { + using range_category = input_range_tag; + using value_type = T; + using reference = T &; + using size_type = size_t; + using difference_type = stream_off_t; + + generator() = default; + + template + generator(F &&func, size_t ss = COROUTINE_DEFAULT_STACK_SIZE): + p_ptr(new coroutine{std::forward(func), ss}) + { + p_item = (*p_ptr)(); + } + + bool empty() const { + return !p_item; + } + + void pop_front() { + if (!*p_ptr) { + p_item = (*p_ptr)(); + } else { + p_item = std::nullopt; + } + } + + reference front() const { + return p_item.value(); + } + + bool equals_front(generator const &g) { + return p_ptr == g.p_ptr; + } +private: + std::shared_ptr> p_ptr; + mutable std::optional p_item; +}; + } /* namespace ostd */ #endif