Skip to content

change the common domain computation to use std::common_type #1451

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

Merged
merged 2 commits into from
Dec 18, 2024
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
2 changes: 1 addition & 1 deletion include/exec/static_thread_pool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ namespace exec {
}

public:
struct domain {
struct domain : stdexec::default_domain {
// For eager customization
template <sender_expr_for<bulk_t> Sender>
auto transform_sender(Sender&& sndr) const noexcept {
Expand Down
116 changes: 65 additions & 51 deletions include/stdexec/__detail/__domain.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "__meta.hpp"

#include "../functional.hpp"
#include "__utility.hpp"

namespace stdexec {

Expand Down Expand Up @@ -78,7 +79,7 @@ namespace stdexec {
};

template <class _Sender>
constexpr bool __is_nothrow_transform_sender() {
constexpr bool __is_nothrow_transform_sender() noexcept {
if constexpr (__callable<__sexpr_apply_t, _Sender, __domain::__legacy_customization>) {
return __nothrow_callable<__sexpr_apply_t, _Sender, __domain::__legacy_customization>;
} else if constexpr (__domain::__has_default_transform_sender<_Sender>) {
Expand All @@ -100,6 +101,43 @@ namespace stdexec {
}
} // namespace __domain

namespace __detail {
///////////////////////////////////////////////////////////////////////////
template <class _Env, class _Tag>
using __completion_scheduler_for =
__meval_or<__call_result_t, __none_such, get_completion_scheduler_t<_Tag>, _Env>;

template <class _Env, class _Tag>
using __completion_domain_for =
__meval_or<__call_result_t, __none_such, get_domain_t, __completion_scheduler_for<_Env, _Tag>>;

// Check the value, error, and stopped channels for completion schedulers.
// Of the completion schedulers that are known, they must all have compatible
// domains. This computes that domain, or else returns __none_such if there
// are no completion schedulers or if they don't specify a domain.
template <class _Env>
struct __completion_domain_or_none_
: __mdefer_<
__mtransform<
__mbind_front_q<__completion_domain_for, _Env>,
__mremove<__none_such, __munique<__msingle_or<__none_such>>>>,
set_value_t,
set_error_t,
set_stopped_t> { };

template <class _Sender>
using __completion_domain_or_none = __t<__completion_domain_or_none_<env_of_t<_Sender>>>;

template <class _Sender>
concept __consistent_completion_domains = __mvalid<__completion_domain_or_none, _Sender>;

template <class _Sender>
concept __has_completion_domain = (!same_as<__completion_domain_or_none<_Sender>, __none_such>);

template <__has_completion_domain _Sender>
using __completion_domain_of = __completion_domain_or_none<_Sender>;
} // namespace __detail

struct default_domain {
default_domain() = default;

Expand Down Expand Up @@ -159,43 +197,6 @@ namespace stdexec {
}
};

/////////////////////////////////////////////////////////////////////////////
namespace __detail {
template <class _Env, class _Tag>
using __completion_scheduler_for =
__meval_or<__call_result_t, __none_such, get_completion_scheduler_t<_Tag>, _Env>;

template <class _Env, class _Tag>
using __completion_domain_for =
__meval_or<__call_result_t, __none_such, get_domain_t, __completion_scheduler_for<_Env, _Tag>>;

// Check the value, error, and stopped channels for completion schedulers.
// Of the completion schedulers that are known, they must all have compatible
// domains. This computes that domain, or else returns __none_such if there
// are no completion schedulers or if they don't specify a domain.
template <class _Env>
struct __completion_domain_or_none_
: __mdefer_<
__mtransform<
__mbind_front_q<__completion_domain_for, _Env>,
__mremove<__none_such, __munique<__msingle_or<__none_such>>>>,
set_value_t,
set_error_t,
set_stopped_t> { };

template <class _Sender>
using __completion_domain_or_none = __t<__completion_domain_or_none_<env_of_t<_Sender>>>;

template <class _Sender>
concept __consistent_completion_domains = __mvalid<__completion_domain_or_none, _Sender>;

template <class _Sender>
concept __has_completion_domain = (!same_as<__completion_domain_or_none<_Sender>, __none_such>);

template <__has_completion_domain _Sender>
using __completion_domain_of = __completion_domain_or_none<_Sender>;
} // namespace __detail

/////////////////////////////////////////////////////////////////////////////
//! Function object implementing `get-domain-early(snd)`
//! from [exec.snd.general] item 3.9. It is the first well-formed expression of
Expand Down Expand Up @@ -252,22 +253,35 @@ namespace stdexec {
template <class _Sender, class _Env>
using __late_domain_of_t = __call_result_t<__get_late_domain_t, _Sender, _Env>;

namespace __domain {
struct __common_domain_fn {
static auto __common_domain() noexcept -> default_domain {
return {};
}
/////////////////////////////////////////////////////////////////////////////
// dependent_domain
struct dependent_domain {
// defined in __transform_sender.hpp
template <class _Sender, class _Env>
static constexpr auto __is_nothrow_transform_sender() noexcept -> bool;

template <class _Domain, class... _OtherDomains>
requires __all_of<_Domain, _OtherDomains...>
static auto __common_domain(_Domain __domain, _OtherDomains...) noexcept -> _Domain {
return static_cast<_Domain&&>(__domain);
}
// defined in __transform_sender.hpp
template <sender_expr _Sender, class _Env>
requires same_as<__early_domain_of_t<_Sender>, dependent_domain>
STDEXEC_ATTRIBUTE((always_inline))
decltype(auto)
transform_sender(_Sender&& __sndr, const _Env& __env) const
noexcept(__is_nothrow_transform_sender<_Sender, _Env>());
};

namespace __domain {
struct __common_domain_fn {
template <class... _Domains>
static auto __common_domain(_Domains...) noexcept //
-> __if_c<__one_of<dependent_domain, _Domains...>, dependent_domain, __none_such> {
return {};
static auto __common_domain(_Domains...) noexcept {
if constexpr (sizeof...(_Domains) == 0) {
return default_domain();
} else if constexpr (__one_of<dependent_domain, _Domains...>) {
return dependent_domain();
} else if constexpr (stdexec::__mvalid<std::common_type_t, _Domains...>) {
return std::common_type_t<_Domains...>();
} else {
return __none_such();
}
}

auto operator()(__ignore, __ignore, const auto&... __sndrs) const noexcept {
Expand Down
14 changes: 0 additions & 14 deletions include/stdexec/__detail/__transform_sender.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,6 @@ STDEXEC_PRAGMA_PUSH()
STDEXEC_PRAGMA_IGNORE_EDG(type_qualifiers_ignored_on_reference)

namespace stdexec {
/////////////////////////////////////////////////////////////////////////////
// dependent_domain
struct dependent_domain {
template <class _Sender, class _Env>
static constexpr auto __is_nothrow_transform_sender() noexcept -> bool;

template <sender_expr _Sender, class _Env>
requires same_as<__early_domain_of_t<_Sender>, dependent_domain>
STDEXEC_ATTRIBUTE((always_inline))
decltype(auto)
transform_sender(_Sender&& __sndr, const _Env& __env) const
noexcept(__is_nothrow_transform_sender<_Sender, _Env>());
};

/////////////////////////////////////////////////////////////////////////////
// [execution.transform_sender]
namespace __domain {
Expand Down
Loading