Skip to content

Commit

Permalink
Merge pull request #10 from beman-project/basic-sender
Browse files Browse the repository at this point in the history
Basic sender
  • Loading branch information
dietmarkuehl authored Aug 31, 2024
2 parents 087cd9f + 221a90d commit 4dea907
Show file tree
Hide file tree
Showing 6 changed files with 339 additions and 1 deletion.
40 changes: 40 additions & 0 deletions include/beman/execution26/detail/get_domain_early.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// include/beman/execution26/detail/get_domain_early.hpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_DOMAIN_EARLY
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_DOMAIN_EARLY

#include <beman/execution26/detail/completion_domain.hpp>
#include <beman/execution26/detail/default_domain.hpp>
#include <beman/execution26/detail/get_domain.hpp>
#include <beman/execution26/detail/get_env.hpp>

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

namespace beman::execution26::detail
{
template <typename Sender>
constexpr auto get_domain_early(Sender const& sender) noexcept
{
if constexpr (requires{
::beman::execution26::get_domain(
::beman::execution26::get_env(sender)
);
})
return decltype(
::beman::execution26::get_domain(
::beman::execution26::get_env(sender)
)
){};
else if constexpr (requires{
::beman::execution26::detail::completion_domain(sender);
})
return decltype(::beman::execution26::detail::completion_domain(sender)){};
else
return ::beman::execution26::default_domain{};
}
}

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

#endif
35 changes: 35 additions & 0 deletions include/beman/execution26/detail/make_sender.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// include/beman/execution26/detail/make_sender.hpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_MAKE_SENDER
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_MAKE_SENDER

#include <beman/execution26/detail/basic_sender.hpp>
#include <beman/execution26/detail/movable_value.hpp>
#include <beman/execution26/detail/sender.hpp>
#include <concepts>
#include <type_traits>

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

namespace beman::execution26::detail
{
struct make_sender_empty {};

template <typename Tag,
typename Data = ::beman::execution26::detail::make_sender_empty,
typename... Child>
requires ::std::semiregular<Tag>
&& ::beman::execution26::detail::movable_value<Data>
&& (::beman::execution26::sender<Child> && ...)
constexpr auto make_sender(Tag tag, Data&& data, Child&&... child)
{
return ::beman::execution26::detail::basic_sender<
Tag, ::std::decay_t<Data>, ::std::decay_t<Child>...
>{tag, ::std::forward<Data>(data), child...};
}
}

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

#endif
61 changes: 61 additions & 0 deletions include/beman/execution26/detail/sender_adaptor.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// include/beman/execution26/detail/sender_adaptor.hpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_SENDER_ADAPTOR
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_SENDER_ADAPTOR

#include <beman/execution26/detail/sender.hpp>
#include <beman/execution26/detail/sender_adaptor_closure.hpp>
#include <beman/execution26/detail/sender_decompose.hpp>
#include <beman/execution26/detail/product_type.hpp>
#include <type_traits>
#include <utility>

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

namespace beman::execution26::detail
{
template <typename Adaptor, typename T0, typename... T>
struct sender_adaptor
: ::beman::execution26::detail::product_type<
::std::decay_t<Adaptor>, ::std::decay_t<T0>, ::std::decay_t<T>...>
, ::beman::execution26::sender_adaptor_closure<sender_adaptor<Adaptor, T0, T...>>
{
template <::beman::execution26::sender Sender>
static auto apply(Sender&& sender, auto&& self)
{
using base_type = ::beman::execution26::detail::product_type<
::std::decay_t<Adaptor>, ::std::decay_t<T0>, ::std::decay_t<T>...>;
static constexpr ::beman::execution26::detail::sender_any_t at{};
if constexpr (requires{ base_type{ at, at, at, at }; })
{
auto&&[adaptor, arg0, arg1, arg2] = self;
return adaptor(::std::forward<Sender>(sender), arg0, arg1, arg2);
}
if constexpr (requires{ base_type{ at, at, at }; })
{
auto&&[adaptor, arg0, arg1] = self;
return adaptor(::std::forward<Sender>(sender), arg0, arg1);
}
else if constexpr (requires{ base_type{ at, at }; })
{
auto&&[adaptor, arg0] = self;
return adaptor(::std::forward<Sender>(sender), arg0);
}
}
template <::beman::execution26::sender Sender>
auto operator()(Sender&& sender)
{
return apply(::std::forward<Sender>(sender), *this);
}
template <::beman::execution26::sender Sender>
auto operator()(Sender&& sender) const
{
return apply(::std::forward<Sender>(sender), *this);
}
};
}

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

#endif
46 changes: 46 additions & 0 deletions include/beman/execution26/detail/sender_adaptor_closure.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// include/beman/execution26/detail/sender_adaptor_closure.hpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_SENDER_ADAPTOR_CLOSURE
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_SENDER_ADAPTOR_CLOSURE

#include <beman/execution26/detail/sender.hpp>
#include <concepts>
#include <type_traits>
#include <utility>

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

namespace beman::execution26::detail::pipeable
{
struct sender_adaptor_closure_base {};
}

namespace beman::execution26
{
template <typename>
struct sender_adaptor_closure
: ::beman::execution26::detail::pipeable::sender_adaptor_closure_base
{
};
}

namespace beman::execution26::detail::pipeable
{
template <::beman::execution26::sender Sender, typename Adaptor>
requires (not ::beman::execution26::sender<Adaptor>)
&& ::std::derived_from<::std::decay_t<Adaptor>,
::beman::execution26::sender_adaptor_closure<::std::decay_t<Adaptor>>>
&& requires(Sender&& sender, Adaptor&& adaptor)
{
{ adaptor(::std::forward<Sender>(sender)) } -> ::beman::execution26::sender;
}
auto operator| (Sender&& sender, Adaptor&& adaptor)
{
return adaptor(::std::forward<Sender>(sender));
}
}

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

#endif
87 changes: 86 additions & 1 deletion src/beman/execution26/tests/exec-snd-expos.pass.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// src/beman/execution26/tests/exe-snd-expos.pass.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <beman/execution26/detail/make_sender.hpp>
#include <beman/execution26/detail/basic_sender.hpp>
#include <beman/execution26/detail/completion_signatures_for.hpp>
#include <beman/execution26/detail/connect_all_result.hpp>
Expand All @@ -15,6 +16,7 @@
#include <beman/execution26/detail/sched_env.hpp>
#include <beman/execution26/detail/sender.hpp>
#include <beman/execution26/detail/query_with_default.hpp>
#include <beman/execution26/detail/get_domain_early.hpp>
#include <beman/execution26/detail/get_domain_late.hpp>
#include <beman/execution26/detail/default_impls.hpp>
#include <beman/execution26/detail/impls_for.hpp>
Expand Down Expand Up @@ -332,6 +334,17 @@ namespace
auto operator== (scheduler const&) const -> bool = default;
};

template <>
struct env<domain>
{
template <typename Tag>
auto query(test_std::get_completion_scheduler_t<Tag> const&) const noexcept
-> scheduler<domain>
{
return {};
}
};

template <>
struct env<common>
{
Expand Down Expand Up @@ -407,8 +420,52 @@ namespace
assert(result2.default_value == 74);
}

auto test_get_domain_early() -> void
{
struct plain_sender
{
using sender_concept = test_std::sender_t;
};
static_assert(test_std::sender<plain_sender>);
static_assert(std::same_as<
test_std::default_domain,
decltype(test_detail::get_domain_early(plain_sender{}))
>);

namespace cd = completion_domain;
static_assert(test_std::sender<cd::sender<cd::domain>>);
static_assert(std::same_as<
cd::domain,
decltype(test_detail::get_domain_early(cd::sender<cd::domain>{}))
>);

struct sender_with_domain
{
using sender_concept = test_std::sender_t;
struct domain {};
struct env
{
auto query(test_std::get_domain_t const&) const noexcept -> domain { return {}; }
};
auto get_env() const noexcept -> env { return {}; }
};
static_assert(test_std::sender<sender_with_domain>);
static_assert(std::same_as<
sender_with_domain::env,
decltype(test_std::get_env(sender_with_domain{}))
>);
static_assert(std::same_as<
sender_with_domain::domain,
decltype(test_std::get_domain(sender_with_domain::env{}))
>);
static_assert(std::same_as<
sender_with_domain::domain,
decltype(test_detail::get_domain_early(sender_with_domain{}))
>);
}

template <typename Expect>
auto test_get_domain_late(auto sender, auto env)
auto test_get_domain_late(auto sender, auto env) -> void
{
static_assert(test_std::sender<decltype(sender)>);
static_assert(test_detail::queryable<decltype(env)>);
Expand Down Expand Up @@ -451,6 +508,7 @@ namespace
{
using sender_concept = test_std::sender_t;
};
static_assert(test_std::sender<no_domain_sender>);
test_get_domain_late<test_std::default_domain>(no_domain_sender{}, test_std::empty_env{});

struct scheduler_env
Expand Down Expand Up @@ -1175,6 +1233,31 @@ namespace
basic_sender::indices_for
>);
}

template <typename T>
auto test_make_sender() -> void
{
{
auto sender{test_detail::make_sender(tag{}, {})};
static_assert(test_std::sender<decltype(sender)>);
}
{
auto sender{test_detail::make_sender(tag{}, int{17})};
static_assert(test_std::sender<decltype(sender)>);
static_assert(std::same_as<test_detail::basic_sender<tag, int>, decltype(sender)>);
}
{
static_assert(not requires{ test_detail::make_sender(tag{}, int{17}, T()); });
}
{
auto sender{test_detail::make_sender(tag{}, int{17}, sender0{})};
static_assert(test_std::sender<decltype(sender)>);
static_assert(std::same_as<
test_detail::basic_sender<tag, int, sender0>,
decltype(sender)
>);
}
}
}

auto main() -> int
Expand All @@ -1186,6 +1269,7 @@ auto main() -> int
test_sched_env();
test_completion_domain();
test_query_with_default();
test_get_domain_early();
test_get_domain_late();
test_default_impls();
test_impls_for();
Expand All @@ -1202,4 +1286,5 @@ auto main() -> int
test_basic_operation();
test_completion_signatures_for();
test_basic_sender();
test_make_sender<int>();
}
Loading

0 comments on commit 4dea907

Please sign in to comment.