Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get completion behaviour #115

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
38 changes: 37 additions & 1 deletion include/beman/execution26/detail/basic_sender.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include <beman/execution26/detail/sender.hpp>
#include <beman/execution26/detail/sender_decompose.hpp>
#include <beman/execution26/detail/connect.hpp>
#include <beman/execution26/detail/get_completion_signatures.hpp>
#include <beman/execution26/detail/get_completion_behaviour.hpp>
#include <utility>

#include <beman/execution26/detail/suppress_push.hpp>
Expand All @@ -39,6 +39,36 @@ struct basic_sender : ::beman::execution26::detail::product_type<Tag, Data, Chil
data.children);
}

#if __cpp_explicit_this_parameter < 302110L //-dk:TODO need to figure out how to use explicit this with forwarding
template <class Env>
constexpr auto get_completion_behaviour(Env&& env) noexcept -> decltype(auto) {
return []<typename Self>(Self&& self, Env&& env) -> decltype(auto) {
auto data{::beman::execution26::detail::get_sender_data(self)};
return ::std::apply(
[&data, &env](auto&&... cs) {
return ::beman::execution26::detail::impls_for<Tag>::get_completion_behaviour(
::std::forward<Env>(env),
::beman::execution26::detail::forward_like<Self>(data.data),
::beman::execution26::detail::forward_like<Self>(cs)...);
},
::beman::execution26::detail::forward_like<Self>(data.children));
}(*this, ::std::forward<Env>(env));
}
#else
template <class Env>
constexpr auto get_completion_behaviour(this Self&& self, Env&& env) noexcept -> decltype(auto) {
auto data{::beman::execution26::detail::get_sender_data(self)};
return ::std::apply(
[&data, &env](auto&&... cs) {
return ::beman::execution26::detail::impls_for<Tag>::get_completion_behaviour(
::std::forward<Env>(env),
::beman::execution26::detail::forward_like<Self>(data.data),
::beman::execution26::detail::forward_like<Self>(cs)...);
},
::beman::execution26::detail::forward_like<Self>(data.children));
}
#endif

template <typename Receiver>
requires(not::beman::execution26::receiver<Receiver>)
auto connect(Receiver receiver) = BEMAN_EXECUTION26_DELETE("the passed receiver doesn't model receiver");
Expand Down Expand Up @@ -101,6 +131,12 @@ struct basic_sender : ::beman::execution26::detail::product_type<Tag, Data, Chil
-> ::beman::execution26::detail::completion_signatures_for<Self, Env> {
return {};
}

template <::beman::execution26::detail::decays_to<basic_sender> Self, typename Env>
auto get_completion_behaviour(this Self&&, Env&&) noexcept
-> ::beman::execution26::detail::completion_signatures_for<Self, Env> {
return {};
}
#endif
};
} // namespace beman::execution26::detail
Expand Down
13 changes: 13 additions & 0 deletions include/beman/execution26/detail/completion_behaviour.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// include/beman/execution26/detail/completion_behaviour.hpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_COMPLETION_BEHAVIOUR
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_COMPLETION_BEHAVIOUR

#include <cstdint>

namespace beman::execution26 {
enum class completion_behaviour : std::uint8_t { inline_completion, synchronous, asynchronous, unknown };
} // namespace beman::execution26

#endif
5 changes: 5 additions & 0 deletions include/beman/execution26/detail/default_impls.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <beman/execution26/detail/product_type.hpp>
#include <beman/execution26/detail/sender_decompose.hpp>
#include <beman/execution26/detail/start.hpp>
#include <beman/execution26/detail/get_completion_behaviour.hpp>

#include <utility>

Expand Down Expand Up @@ -52,6 +53,10 @@ struct default_impls {
static_assert(Index::value == 0);
Tag()(::std::move(receiver), ::std::forward<Args>(args)...);
};
static constexpr auto get_completion_behaviour =
[](const auto& /* env */, const auto& /* data */, const auto&... /* children */) noexcept {
return ::beman::execution26::completion_behaviour::unknown;
};
};
} // namespace beman::execution26::detail

Expand Down
14 changes: 7 additions & 7 deletions include/beman/execution26/detail/forward_like.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,43 +18,43 @@ struct forward_like_helper;
template <typename T>
struct forward_like_helper {
template <typename U>
static auto forward(U&& u) -> ::std::remove_reference_t<U>&& {
static constexpr auto forward(U&& u) -> ::std::remove_reference_t<U>&& {
return ::std::move(u); // NOLINT(bugprone-move-forwarding-reference)
}
};
template <typename T>
struct forward_like_helper<T&&> {
template <typename U>
static auto forward(U&& u) -> ::std::remove_cvref_t<U>&& {
static constexpr auto forward(U&& u) -> ::std::remove_cvref_t<U>&& {
return ::std::move(u); // NOLINT(bugprone-move-forwarding-reference)
}
};
template <typename T>
struct forward_like_helper<T&> {
template <typename U>
static auto forward(U&& u) -> ::std::remove_cvref_t<U>& {
static constexpr auto forward(U&& u) -> ::std::remove_cvref_t<U>& {
return ::std::forward<U&&>(u);
}
};
template <typename T>
struct forward_like_helper<const T&&> {
template <typename U>
static auto forward(U&& u) -> const ::std::remove_cvref_t<U>&& {
static constexpr auto forward(U&& u) -> const ::std::remove_cvref_t<U>&& {
return ::std::move(u); // NOLINT(bugprone-move-forwarding-reference)
}
};
template <typename T>
struct forward_like_helper<const T&> {
template <typename U>
static auto forward(U&& u) -> const ::std::remove_cvref_t<U>& {
static constexpr auto forward(U&& u) -> const ::std::remove_cvref_t<U>& {
return ::std::forward<U&&>(u);
}
};

// The overload own_forward_like is used for testing on systems
// which actually do provide an implementation.
template <typename T, typename U>
auto own_forward_like(U&& u) noexcept -> decltype(auto) {
constexpr auto own_forward_like(U&& u) noexcept -> decltype(auto) {
return ::beman::execution26::detail::forward_like_helper<T>::forward(::std::forward<U>(u));
}

Expand All @@ -64,7 +64,7 @@ auto own_forward_like(U&& u) noexcept -> decltype(auto) {
* \internal
*/
template <typename T, typename U>
auto forward_like(U&& u) noexcept -> decltype(auto) {
constexpr auto forward_like(U&& u) noexcept -> decltype(auto) {
#if 202207 <= disabled__cpp_lib_forward_like
return ::std::forward_like<T>(::std::forward<U>(u));
#else
Expand Down
73 changes: 73 additions & 0 deletions include/beman/execution26/detail/get_completion_behaviour.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// include/beman/execution26/detail/get_completion_behaviour.hpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_COMPLETION_BEHAVIOUR
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_COMPLETION_BEHAVIOUR

#include <beman/execution26/detail/completion_behaviour.hpp>
#include <beman/execution26/detail/forward_like.hpp>
#include <beman/execution26/detail/is_awaitable.hpp>
#include <beman/execution26/detail/get_domain_late.hpp>
#include <beman/execution26/detail/transform_sender.hpp>

#include <type_traits>

namespace beman::execution26 {

struct get_completion_behaviour_t {
template <class Sender>
constexpr auto operator()(Sender&& sender) const noexcept {
if constexpr (requires { typename ::std::remove_cvref_t<Sender>::completion_behaviour; }) {
return typename ::std::remove_cvref_t<Sender>::completion_behaviour{};
} else if constexpr (requires { ::std::forward<Sender>(sender).get_completion_behaviour(); }) {
return ::std::forward<Sender>(sender).get_completion_behaviour();
} else if constexpr (::beman::execution26::detail::is_awaitable<
::std::remove_cvref_t<Sender>,
::beman::execution26::detail::env_promise<::beman::execution26::empty_env>>) {
return sender.await_ready() ? ::beman::execution26::completion_behaviour::inline_completion
: ::beman::execution26::completion_behaviour::unknown;
} else {
return ::beman::execution26::completion_behaviour::unknown;
}
}

template <class Sender, class Env>
constexpr auto operator()(Sender&& sender, Env&& env) const noexcept {
auto new_sender{[](auto&& sndr, auto&& e) -> decltype(auto) {
auto domain{::beman::execution26::detail::get_domain_late(sndr, e)};
return ::beman::execution26::transform_sender(
domain, ::std::forward<Sender>(sndr), ::std::forward<Env>(e));
}};

using new_sender_type =
::std::remove_cvref_t<decltype(new_sender(::std::forward<Sender>(sender), ::std::forward<Env>(env)))>;
using decayed_env = ::std::remove_cvref_t<Env>;

if constexpr (requires { typename new_sender_type::completion_behaviour; }) {
return typename new_sender_type::completion_behaviour{};
} else if constexpr (requires {
new_sender(::std::forward<Sender>(sender), ::std::forward<Env>(env))
.get_completion_behaviour(std::forward<Env>(env));
}) {
std::remove_cvref_t<Env> copiedEnv(env);
return new_sender(::std::forward<Sender>(sender), ::std::forward<Env>(copiedEnv))
.get_completion_behaviour(std::forward<Env>(env));
} else if constexpr (::beman::execution26::detail::is_awaitable<
new_sender_type,
::beman::execution26::detail::env_promise<decayed_env>>) {
if (new_sender(::std::forward<Sender>(sender), ::std::forward<Env>(env)).await_ready()) {
return completion_behaviour::inline_completion;
} else {
return completion_behaviour::unknown;
}
} else {
return completion_behaviour::unknown;
}
}
};

inline constexpr get_completion_behaviour_t get_completion_behaviour{};

} // namespace beman::execution26

#endif
10 changes: 7 additions & 3 deletions include/beman/execution26/detail/just.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@

namespace beman::execution26::detail {
template <typename Completion, typename... T>
concept just_size = (not::std::same_as<Completion, ::beman::execution26::set_error_t> or 1u == sizeof...(T)) &&
(not::std::same_as<Completion, ::beman::execution26::set_stopped_t> or 0u == sizeof...(T));
concept just_size = (not ::std::same_as<Completion, ::beman::execution26::set_error_t> or 1u == sizeof...(T)) &&
(not ::std::same_as<Completion, ::beman::execution26::set_stopped_t> or 0u == sizeof...(T));
Comment on lines +25 to +26

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[pre-commit] reported by reviewdog 🐶

Suggested change
concept just_size = (not ::std::same_as<Completion, ::beman::execution26::set_error_t> or 1u == sizeof...(T)) &&
(not ::std::same_as<Completion, ::beman::execution26::set_stopped_t> or 0u == sizeof...(T));
concept just_size = (not::std::same_as<Completion, ::beman::execution26::set_error_t> or 1u == sizeof...(T)) &&
(not::std::same_as<Completion, ::beman::execution26::set_stopped_t> or 0u == sizeof...(T));

template <typename Completion>
struct just_t {
template <typename... T>
requires ::beman::execution26::detail::just_size<Completion, T...> &&
(::std::movable<::std::decay_t<T>> && ...)
auto operator()(T&&... arg) const {
constexpr auto operator()(T&&... arg) const {
return ::beman::execution26::detail::make_sender(
*this, ::beman::execution26::detail::product_type{::std::forward<T>(arg)...});
}
Expand All @@ -49,6 +49,10 @@ struct impls_for<just_t<Completion>> : ::beman::execution26::detail::default_imp
Completion()(::std::move(receiver), ::std::move(state.template get<I>())...);
}(::std::make_index_sequence<State::size()>{});
};

static constexpr auto get_completion_behaviour = [](const auto&, const auto&, const auto&...) {
return ::beman::execution26::completion_behaviour::inline_completion;
};
};
} // namespace beman::execution26::detail

Expand Down
24 changes: 13 additions & 11 deletions include/beman/execution26/detail/product_type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,34 +29,35 @@ struct product_type_base<::std::index_sequence<I...>, T...>
static constexpr bool is_product_type{true};

template <::std::size_t J, typename S>
static auto element_get(::beman::execution26::detail::product_type_element<J, S>& self) noexcept -> S& {
static constexpr auto element_get(::beman::execution26::detail::product_type_element<J, S>& self) noexcept -> S& {
return self.value;
}
template <::std::size_t J, typename S>
static auto element_get(::beman::execution26::detail::product_type_element<J, S>&& self) noexcept -> S&& {
static constexpr auto
element_get(::beman::execution26::detail::product_type_element<J, S>&& self) noexcept -> S&& {
Comment on lines +36 to +37

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[pre-commit] reported by reviewdog 🐶

Suggested change
static constexpr auto
element_get(::beman::execution26::detail::product_type_element<J, S>&& self) noexcept -> S&& {
static constexpr auto element_get(::beman::execution26::detail::product_type_element<J, S>&& self) noexcept
-> S&& {

return ::std::move(self.value);
}
template <::std::size_t J, typename S>
static auto element_get(const ::beman::execution26::detail::product_type_element<J, S>& self) noexcept
-> const S& {
static constexpr auto
element_get(const ::beman::execution26::detail::product_type_element<J, S>& self) noexcept -> const S& {
Comment on lines +41 to +42

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[pre-commit] reported by reviewdog 🐶

Suggested change
static constexpr auto
element_get(const ::beman::execution26::detail::product_type_element<J, S>& self) noexcept -> const S& {
static constexpr auto element_get(const ::beman::execution26::detail::product_type_element<J, S>& self) noexcept
-> const S& {

return self.value;
}

template <::std::size_t J>
auto get() & -> decltype(auto) {
constexpr auto get() & -> decltype(auto) {
return this->element_get<J>(*this);
}
template <::std::size_t J>
auto get() && -> decltype(auto) {
constexpr auto get() && -> decltype(auto) {
return this->element_get<J>(::std::move(*this));
}
template <::std::size_t J>
auto get() const& -> decltype(auto) {
constexpr auto get() const& -> decltype(auto) {
return this->element_get<J>(*this);
}

template <::std::size_t J, typename Allocator, typename Self>
static auto make_element(Allocator&& alloc, Self&& self) -> decltype(auto) {
static constexpr auto make_element(Allocator&& alloc, Self&& self) -> decltype(auto) {
using type = ::std::remove_cvref_t<decltype(product_type_base::element_get<J>(std::forward<Self>(self)))>;
if constexpr (::std::uses_allocator_v<type, Allocator>)
return ::std::make_obj_using_allocator<type>(alloc,
Expand All @@ -65,7 +66,7 @@ struct product_type_base<::std::index_sequence<I...>, T...>
return product_type_base::element_get<J>(std::forward<Self>(self));
}

auto operator==(const product_type_base&) const -> bool = default;
constexpr auto operator==(const product_type_base&) const -> bool = default;
};

template <typename T>
Expand All @@ -74,12 +75,13 @@ concept is_product_type_c = requires(const T& t) { T::is_product_type; };
template <typename... T>
struct product_type : ::beman::execution26::detail::product_type_base<::std::index_sequence_for<T...>, T...> {
template <typename Allocator, typename Product, std::size_t... I>
static auto make_from(Allocator&& allocator, Product&& product, std::index_sequence<I...>) -> product_type {
static constexpr auto
make_from(Allocator&& allocator, Product&& product, std::index_sequence<I...>) -> product_type {
Comment on lines +78 to +79

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[pre-commit] reported by reviewdog 🐶

Suggested change
static constexpr auto
make_from(Allocator&& allocator, Product&& product, std::index_sequence<I...>) -> product_type {
static constexpr auto make_from(Allocator&& allocator, Product&& product, std::index_sequence<I...>)
-> product_type {

return {product_type::template make_element<I>(allocator, ::std::forward<Product>(product))...};
}

template <typename Allocator, typename Product>
static auto make_from(Allocator&& allocator, Product&& product) -> product_type {
static constexpr auto make_from(Allocator&& allocator, Product&& product) -> product_type {
return product_type::make_from(
::std::forward<Allocator>(allocator), ::std::forward<Product>(product), ::std::index_sequence_for<T...>{});
}
Expand Down
4 changes: 2 additions & 2 deletions include/beman/execution26/detail/sender_decompose.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ struct sender_data {
};

template <typename Sender>
auto get_sender_data(Sender&& sender) {
constexpr auto get_sender_data(Sender&& sender) {
#if 0
//-dk:TODO should use a dynamic/language approach:
auto&& [tag, data, ... children] = sender;
Expand Down Expand Up @@ -82,7 +82,7 @@ auto get_sender_data(Sender&& sender) {
}

template <typename Sender>
auto get_sender_meta(Sender&& sender) {
constexpr auto get_sender_meta(Sender&& sender) {
using type = decltype(get_sender_data(sender));
return sender_meta<typename type::tag_type, typename type::data_type, typename type::children_type>{};
}
Expand Down
2 changes: 2 additions & 0 deletions src/beman/execution26/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ target_sources(
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/child_type.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/class_type.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/common.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/completion_behaviour.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/completion_domain.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/completion_signature.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/completion_signatures.hpp
Expand Down Expand Up @@ -84,6 +85,7 @@ target_sources(
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/gather_signatures.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/get_allocator.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/get_awaiter.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/get_completion_behaviour.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/get_completion_scheduler.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/get_completion_signatures.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/get_delegation_scheduler.hpp
Expand Down
1 change: 1 addition & 0 deletions tests/beman/execution26/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ list(
exec-general.test
exec-get-allocator.test
exec-get-compl-sched.test
exec-get-completion-behaviour.test
exec-get-delegation-scheduler.test
exec-get-domain.test
exec-get-env.test
Expand Down
Loading
Loading