Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions include/beman/task/detail/awaiter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <beman/task/detail/handle.hpp>
#include <beman/task/detail/state_base.hpp>
#include <beman/task/detail/state_rep.hpp>
#include <coroutine>
#include <utility>

Expand Down Expand Up @@ -45,18 +46,20 @@ struct awaiter_op_t<Awaiter, ParentPromise, false> {
};

template <typename Value, typename Env, typename OwnPromise, typename ParentPromise>
class awaiter : public ::beman::task::detail::state_base<Value, Env> {
class awaiter : public ::beman::task::detail::state_base<Value, Env>,
::beman::task::detail::state_rep<Env, ::beman::task::detail::handle<OwnPromise>> {
public:
using stop_token_type = typename ::beman::task::detail::state_base<Value, Env>::stop_token_type;
using scheduler_type = typename ::beman::task::detail::state_base<Value, Env>::scheduler_type;

explicit awaiter(::beman::task::detail::handle<OwnPromise> h) : handle(::std::move(h)) {}
explicit awaiter(::beman::task::detail::handle<OwnPromise> h)
: ::beman::task::detail::state_rep<Env, ::beman::task::detail::handle<OwnPromise>>(std::move(h)) {}
constexpr auto await_ready() const noexcept -> bool { return false; }
auto await_suspend(::std::coroutine_handle<ParentPromise> parent) noexcept {
this->scheduler.emplace(
this->template from_env<scheduler_type>(::beman::execution::get_env(parent.promise())));
this->parent = ::std::move(parent);
return this->handle.start(this);
return this->receiver.start(this);
}
auto await_resume() { return this->result_resume(); }

Expand All @@ -79,18 +82,18 @@ class awaiter : public ::beman::task::detail::state_base<Value, Env> {
return this->actual_complete();
}
auto actual_complete() -> std::coroutine_handle<> {
return this->no_completion_set() ? this->parent.promise().unhandled_stopped() : ::std::move(this->parent);
return this->::beman::task::detail::state_base<Value, Env>::no_completion_set()
? this->parent.promise().unhandled_stopped()
: ::std::move(this->parent);
}
auto do_get_scheduler() -> scheduler_type override { return *this->scheduler; }
auto do_set_scheduler(scheduler_type other) -> scheduler_type override {
return ::std::exchange(*this->scheduler, other);
}
auto do_get_stop_token() -> stop_token_type override { return {}; }
auto do_get_environment() -> Env& override { return this->env; }
auto do_get_environment() -> Env& override { return this->context; }

Env env;
::std::optional<scheduler_type> scheduler;
::beman::task::detail::handle<OwnPromise> handle;
::std::coroutine_handle<ParentPromise> parent{};
::std::optional<awaiter_op_t<awaiter, ParentPromise>> reschedule{};
};
Expand Down
1 change: 1 addition & 0 deletions include/beman/task/detail/handle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class handle {
auto release() -> ::std::coroutine_handle<P> {
return ::std::coroutine_handle<P>::from_promise(*this->h.release());
}
auto get_env() const noexcept { return ::beman::execution::get_env(*this->h); }
};

} // namespace beman::task::detail
Expand Down
1 change: 1 addition & 0 deletions include/beman/task/detail/result_type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ class result_type<Stop, Value, ::beman::execution::completion_signatures<>> {
auto set_value(T&& value) -> void {
this->result.template emplace<1u>(::std::forward<T>(value));
}
auto no_completion_set() const noexcept -> bool { return this->result.index() == 0u; }

/**
* \brief Call the completion function according to the current result.
Expand Down
34 changes: 2 additions & 32 deletions include/beman/task/detail/state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,46 +4,16 @@
#ifndef INCLUDED_INCLUDE_BEMAN_TASK_DETAIL_STATE
#define INCLUDED_INCLUDE_BEMAN_TASK_DETAIL_STATE

#include <beman/task/detail/state_base.hpp>
#include <beman/task/detail/promise_type.hpp>
#include <beman/task/detail/state_base.hpp>
#include <beman/task/detail/state_rep.hpp>
#include <beman/task/detail/stop_source.hpp>
#include <type_traits>
#include <utility>

// ----------------------------------------------------------------------------

namespace beman::task::detail {
template <typename C, typename Receiver>
struct state_rep {
std::remove_cvref_t<Receiver> receiver;
C context;
template <typename R>
state_rep(R&& r) : receiver(std::forward<R>(r)), context() {}
};
template <typename C, typename Receiver>
requires requires { C(::beman::execution::get_env(std::declval<std::remove_cvref_t<Receiver>&>())); } &&
(not requires(const Receiver& receiver) {
typename C::template env_type<decltype(::beman::execution::get_env(receiver))>;
})
struct state_rep<C, Receiver> {
std::remove_cvref_t<Receiver> receiver;
C context;
template <typename R>
state_rep(R&& r) : receiver(std::forward<R>(r)), context(::beman::execution::get_env(this->receiver)) {}
};
template <typename C, typename Receiver>
requires requires(const Receiver& receiver) {
typename C::template env_type<decltype(::beman::execution::get_env(receiver))>;
}
struct state_rep<C, Receiver> {
using upstream_env = decltype(::beman::execution::get_env(std::declval<std::remove_cvref_t<Receiver>&>()));
std::remove_cvref_t<Receiver> receiver;
typename C::template env_type<upstream_env> own_env;
C context;
template <typename R>
state_rep(R&& r)
: receiver(std::forward<R>(r)), own_env(::beman::execution::get_env(this->receiver)), context(this->own_env) {}
};

template <typename Task, typename T, typename C, typename Receiver>
struct state : ::beman::task::detail::state_base<T, C>, ::beman::task::detail::state_rep<C, Receiver> {
Expand Down
48 changes: 48 additions & 0 deletions include/beman/task/detail/state_rep.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// include/beman/task/detail/state_rep.hpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifndef INCLUDED_INCLUDE_BEMAN_TASK_DETAIL_STATE_REP
#define INCLUDED_INCLUDE_BEMAN_TASK_DETAIL_STATE_REP

#include <beman/execution/execution.hpp>
#include <utility>

// ----------------------------------------------------------------------------

namespace beman::task::detail {
template <typename C, typename Receiver>
struct state_rep {
std::remove_cvref_t<Receiver> receiver;
C context;
template <typename R>
state_rep(R&& r) : receiver(std::forward<R>(r)), context() {}
};
template <typename C, typename Receiver>
requires requires { C(::beman::execution::get_env(std::declval<std::remove_cvref_t<Receiver>&>())); } &&
(not requires(const Receiver& receiver) {
typename C::template env_type<decltype(::beman::execution::get_env(receiver))>;
})
struct state_rep<C, Receiver> {
std::remove_cvref_t<Receiver> receiver;
C context;
template <typename R>
state_rep(R&& r) : receiver(std::forward<R>(r)), context(::beman::execution::get_env(this->receiver)) {}
};
template <typename C, typename Receiver>
requires requires(const Receiver& receiver) {
typename C::template env_type<decltype(::beman::execution::get_env(receiver))>;
}
struct state_rep<C, Receiver> {
using upstream_env = decltype(::beman::execution::get_env(std::declval<std::remove_cvref_t<Receiver>&>()));
std::remove_cvref_t<Receiver> receiver;
typename C::template env_type<upstream_env> own_env;
C context;
template <typename R>
state_rep(R&& r)
: receiver(std::forward<R>(r)), own_env(::beman::execution::get_env(this->receiver)), context(this->own_env) {}
};
} // namespace beman::task::detail

// ----------------------------------------------------------------------------

#endif
Loading