forked from OctaForge/libostd
specialize coroutines for zero args
This commit is contained in:
parent
d369bb4b8a
commit
ed514c28a6
|
@ -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<typename R, typename ...A>
|
template<typename R, typename ...A>
|
||||||
struct coro_base {
|
struct coro_base {
|
||||||
coro_base(void (*callp)(void *), size_t ss):
|
coro_base(void (*callp)(void *), size_t ss):
|
||||||
|
@ -186,6 +186,24 @@ namespace detail {
|
||||||
coroutine_context p_ctx;
|
coroutine_context p_ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* yield takes a value but doesn't return any args */
|
||||||
|
template<typename R>
|
||||||
|
struct coro_base<R> {
|
||||||
|
coro_base(void (*callp)(void *), size_t ss):
|
||||||
|
p_ctx(ss, callp, this)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void yield(R &&ret) {
|
||||||
|
p_result = std::forward<R>(ret);
|
||||||
|
p_ctx.yield_jump();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
R p_result;
|
||||||
|
coroutine_context p_ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* yield doesn't take a value and returns args */
|
||||||
template<typename ...A>
|
template<typename ...A>
|
||||||
struct coro_base<void, A...> {
|
struct coro_base<void, A...> {
|
||||||
coro_base(void (*callp)(void *), size_t ss):
|
coro_base(void (*callp)(void *), size_t ss):
|
||||||
|
@ -201,6 +219,21 @@ namespace detail {
|
||||||
std::tuple<A...> p_args;
|
std::tuple<A...> p_args;
|
||||||
coroutine_context p_ctx;
|
coroutine_context p_ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* yield doesn't take a value or return any args */
|
||||||
|
template<>
|
||||||
|
struct coro_base<void> {
|
||||||
|
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 */
|
} /* namespace detail */
|
||||||
|
|
||||||
template<typename R, typename ...A>
|
template<typename R, typename ...A>
|
||||||
|
@ -223,7 +256,9 @@ struct coroutine<R(A...)>: detail::coro_base<R, A...> {
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
R call(A ...args) {
|
R call(A ...args) {
|
||||||
|
if constexpr(sizeof...(A)) {
|
||||||
this->p_args = std::forward_as_tuple(std::forward<A>(args)...);
|
this->p_args = std::forward_as_tuple(std::forward<A>(args)...);
|
||||||
|
}
|
||||||
this->p_ctx.call();
|
this->p_ctx.call();
|
||||||
if constexpr(!std::is_same_v<R, void>) {
|
if constexpr(!std::is_same_v<R, void>) {
|
||||||
return std::forward<R>(this->p_result);
|
return std::forward<R>(this->p_result);
|
||||||
|
@ -232,7 +267,11 @@ private:
|
||||||
|
|
||||||
template<size_t ...I>
|
template<size_t ...I>
|
||||||
R call_helper(std::index_sequence<I...>) {
|
R call_helper(std::index_sequence<I...>) {
|
||||||
|
if constexpr(sizeof...(A)) {
|
||||||
return p_func(*this, std::forward<A>(std::get<I>(this->p_args))...);
|
return p_func(*this, std::forward<A>(std::get<I>(this->p_args))...);
|
||||||
|
} else {
|
||||||
|
return p_func(*this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void context_call(void *data) {
|
static void context_call(void *data) {
|
||||||
|
|
Loading…
Reference in a new issue