From ed514c28a6a2382910c9c76e7ca51bdb815083ad Mon Sep 17 00:00:00 2001 From: q66 Date: Sun, 5 Mar 2017 20:11:39 +0100 Subject: [PATCH] specialize coroutines for zero args --- ostd/coroutine.hh | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/ostd/coroutine.hh b/ostd/coroutine.hh index 3202eb8..b660fca 100644 --- a/ostd/coroutine.hh +++ b/ostd/coroutine.hh @@ -167,7 +167,7 @@ namespace detail { } } - /* we need this because yield is specialized based on result */ + /* default case, yield returns args and takes a value */ template struct coro_base { coro_base(void (*callp)(void *), size_t ss): @@ -186,6 +186,24 @@ namespace detail { coroutine_context p_ctx; }; + /* yield takes a value but doesn't return any args */ + template + struct coro_base { + coro_base(void (*callp)(void *), size_t ss): + p_ctx(ss, callp, this) + {} + + void yield(R &&ret) { + p_result = std::forward(ret); + p_ctx.yield_jump(); + } + + protected: + R p_result; + coroutine_context p_ctx; + }; + + /* yield doesn't take a value and returns args */ template struct coro_base { coro_base(void (*callp)(void *), size_t ss): @@ -201,6 +219,21 @@ namespace detail { std::tuple p_args; coroutine_context p_ctx; }; + + /* yield doesn't take a value or return any args */ + template<> + struct coro_base { + coro_base(void (*callp)(void *), size_t ss): + p_ctx(ss, callp, this) + {} + + void yield() { + p_ctx.yield_jump(); + } + + protected: + coroutine_context p_ctx; + }; } /* namespace detail */ template @@ -223,7 +256,9 @@ struct coroutine: detail::coro_base { } private: R call(A ...args) { - this->p_args = std::forward_as_tuple(std::forward(args)...); + if constexpr(sizeof...(A)) { + this->p_args = std::forward_as_tuple(std::forward(args)...); + } this->p_ctx.call(); if constexpr(!std::is_same_v) { return std::forward(this->p_result); @@ -232,7 +267,11 @@ private: template R call_helper(std::index_sequence) { - return p_func(*this, std::forward(std::get(this->p_args))...); + if constexpr(sizeof...(A)) { + return p_func(*this, std::forward(std::get(this->p_args))...); + } else { + return p_func(*this); + } } static void context_call(void *data) {