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

added then, upon_error, upon_stopped algorithms #20

Merged
merged 5 commits into from
Sep 4, 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
3 changes: 2 additions & 1 deletion docs/questions.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,5 @@ likely observable.
- [exec.sync_wait] are sync_wait(just_error(17)) and sync_wait(just_stopped())
supposed to work? I don't see a reason why a value completion is necessarily
required. As is, they are not because type_idenity_t ends up being used without
argument.
argument.
- [exec.then] p5 seems to miss a space betweend sendr and out_sndr
8 changes: 4 additions & 4 deletions include/beman/execution26/detail/basic_sender.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,25 +72,25 @@ namespace beman::execution26::detail
#if __cpp_explicit_this_parameter < 202110L
template <typename Env>
auto get_completion_signatures(Env&&) &&
-> ::beman::execution26::detail::completion_signatures_for<basic_sender&&, Env>
-> ::beman::execution26::detail::completion_signatures_for<basic_sender, Env>
{
return {};
}
template <typename Env>
auto get_completion_signatures(Env&&) const&&
-> ::beman::execution26::detail::completion_signatures_for<basic_sender const&&, Env>
-> ::beman::execution26::detail::completion_signatures_for<basic_sender, Env>
{
return {};
}
template <typename Env>
auto get_completion_signatures(Env&&) &
-> ::beman::execution26::detail::completion_signatures_for<basic_sender&, Env>
-> ::beman::execution26::detail::completion_signatures_for<basic_sender, Env>
{
return {};
}
template <typename Env>
auto get_completion_signatures(Env&&) const&
-> ::beman::execution26::detail::completion_signatures_for<basic_sender const&, Env>
-> ::beman::execution26::detail::completion_signatures_for<basic_sender, Env>
{
return {};
}
Expand Down
1 change: 1 addition & 0 deletions include/beman/execution26/detail/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#if defined(__GNUC__)
# pragma GCC diagnostic ignored "-Wmissing-braces"
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#endif

#if defined(__clang__)
Expand Down
34 changes: 34 additions & 0 deletions include/beman/execution26/detail/meta_transform.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// include/beman/execution26/detail/meta_transform.hpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_META_TRANSFORM
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_META_TRANSFORM

#include <beman/execution26/detail/meta_contains.hpp>

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

namespace beman::execution26::detail::meta::detail
{
template <template <typename> class Transform, typename List> struct transform;

template <template <typename> class Transform,
template <typename... T> class List,
typename... T>
struct transform<Transform, List<T...>>
{
using type = List<Transform<T>...>;
};
}

namespace beman::execution26::detail::meta
{
template <template <typename> class Transform, typename List>
using transform = typename
::beman::execution26::detail::meta::detail::transform<Transform, List>
::type;
}

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

#endif
35 changes: 21 additions & 14 deletions include/beman/execution26/detail/meta_unique.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,35 @@

namespace beman::execution26::detail::meta::detail
{
template <typename, typename> struct make_unique;
template <typename> struct unique;

template <template <typename...> class List>
struct unique<List<>>
template <template <typename...> class List, typename... R>
struct make_unique<List<R...>, List<>>
{
using type = List<>;
using type = List<R...>;
};
template <template <typename...> class List, typename T>
struct unique<List<T>>

template <template <typename...> class List, typename... R, typename H, typename... T>
struct make_unique<List<R...>, List<H, T...>>
{
using type = List<T>;
using type = typename ::beman::execution26::detail::meta::detail::make_unique<
::std::conditional_t<
::beman::execution26::detail::meta::contains<H, R...>,
List<R...>,
List<R..., H>
>,
List<T...>
>::type;
};

template <template <typename...> class List, typename H, typename... T>
struct unique<List<H, T...>>
template <template <typename...> class List, typename... T>
struct unique<List<T...>>
{
using tail = ::beman::execution26::detail::meta::detail::unique<List<T...>>::type;
using type = ::std::conditional_t<
::beman::execution26::detail::meta::contains<H, T...>,
tail,
::beman::execution26::detail::meta::prepend<H, tail>
>;
using type = typename ::beman::execution26::detail::meta::detail::make_unique<
List<>,
List<T...>
>::type;
};
}

Expand Down
2 changes: 2 additions & 0 deletions include/beman/execution26/detail/sender_adaptor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ namespace beman::execution26::detail
return apply(::std::forward<Sender>(sender), *this);
}
};
template <typename... T>
sender_adaptor(T&&...) -> sender_adaptor<T...>;
}

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

#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_THEN
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_THEN

#include <beman/execution26/detail/call_result_t.hpp>
#include <beman/execution26/detail/completion_signatures.hpp>
#include <beman/execution26/detail/completion_signatures_for.hpp>
#include <beman/execution26/detail/completion_signatures_of_t.hpp>
#include <beman/execution26/detail/default_impls.hpp>
#include <beman/execution26/detail/get_domain_early.hpp>
#include <beman/execution26/detail/impls_for.hpp>
#include <beman/execution26/detail/make_sender.hpp>
#include <beman/execution26/detail/meta_transform.hpp>
#include <beman/execution26/detail/meta_unique.hpp>
#include <beman/execution26/detail/movable_value.hpp>
#include <beman/execution26/detail/sender.hpp>
#include <beman/execution26/detail/sender_adaptor.hpp>
#include <beman/execution26/detail/sender_adaptor_closure.hpp>
#include <beman/execution26/detail/set_error.hpp>
#include <beman/execution26/detail/set_stopped.hpp>
#include <beman/execution26/detail/set_value.hpp>
#include <beman/execution26/detail/transform_sender.hpp>
#include <concepts>
#include <exception>
#include <functional>
#include <utility>

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

namespace beman::execution26::detail
{
template <typename Completion>
struct then_t
: ::beman::execution26::sender_adaptor_closure<then_t<Completion>>
{
template <::beman::execution26::detail::movable_value Fun>
auto operator()(Fun&& fun) const
{
return ::beman::execution26::detail::sender_adaptor{
*this, ::std::forward<Fun>(fun)
};
}
template <::beman::execution26::sender Sender,
::beman::execution26::detail::movable_value Fun>
auto operator()(Sender&& sender, Fun&& fun) const
{
auto domain{::beman::execution26::detail::get_domain_early(sender)};
return ::beman::execution26::transform_sender(
domain,
::beman::execution26::detail::make_sender(
*this,
::std::forward<Fun>(fun),
::std::forward<Sender>(sender)
)
);
}
};

template <typename Completion>
struct impls_for<then_t<Completion>>
: ::beman::execution26::detail::default_impls
{
static constexpr auto complete
= []<typename Tag, typename... Args>
(auto, auto& fun, auto& receiver, Tag, Args&&... args)
noexcept
-> void
{
if constexpr (::std::same_as<Completion, Tag>)
{
try
{
auto invoke = [&]{
return ::std::invoke(::std::move(fun),
::std::forward<Args>(args)...);
};
if constexpr (::std::same_as<void, decltype(invoke())>)
{
invoke();
::beman::execution26::set_value(
::std::move(receiver)
);
}
else
{
::beman::execution26::set_value(
::std::move(receiver),
invoke()
);
}
}
catch (...)
{
::beman::execution26::set_error(
::std::move(receiver),
::std::current_exception()
);
}
}
else
{
Tag()(::std::move(receiver), ::std::forward<Args>(args)...);
}
};
};

template <typename T>
struct then_set_value
{
using type = ::beman::execution26::set_value_t(T);
};
template <>
struct then_set_value<void>
{
using type = ::beman::execution26::set_value_t();
};

template <typename, typename, typename Completion>
struct then_transform
{
using type = Completion;
};

template <typename Fun, typename Replace>
struct then_transform_t
{
template <typename Completion>
using transform = typename
::beman::execution26::detail::then_transform<Fun, Replace, Completion>
::type;
};

template <typename Fun, typename Completion, typename... T>
struct then_transform<Fun, Completion, Completion(T...)>
{
using type = typename ::beman::execution26::detail::then_set_value<
::beman::execution26::detail::call_result_t<Fun, T...>
>::type;
};

template <typename Completion, typename Fun, typename Sender, typename Env>
struct completion_signatures_for_impl<
::beman::execution26::detail::basic_sender<
::beman::execution26::detail::then_t<Completion>,
Fun,
Sender
>,
Env
>
{
using type = ::beman::execution26::detail::meta::unique<
::beman::execution26::detail::meta::transform<
::beman::execution26::detail::then_transform_t<Fun, Completion>::template transform,
::beman::execution26::completion_signatures_of_t<Sender, Env>
>
>;
};
}

namespace beman::execution26
{
using then_t = ::beman::execution26::detail::then_t<::beman::execution26::set_value_t>;
using upon_error_t = ::beman::execution26::detail::then_t<::beman::execution26::set_error_t>;
using upon_stopped_t = ::beman::execution26::detail::then_t<::beman::execution26::set_stopped_t>;

inline constexpr ::beman::execution26::then_t then{};
inline constexpr ::beman::execution26::upon_error_t upon_error{};
inline constexpr ::beman::execution26::upon_stopped_t upon_stopped{};
}

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

#endif
2 changes: 2 additions & 0 deletions src/beman/execution26/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ target_sources(${TARGET_LIBRARY}
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/meta_contains.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/meta_filter.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/meta_prepend.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/meta_transform.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/meta_unique.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/movable_value.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/never_stop_token.hpp
Expand Down Expand Up @@ -123,6 +124,7 @@ target_sources(${TARGET_LIBRARY}
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/stoppable_token.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/sync_wait.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/tag_of_t.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/then.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/transform_sender.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/type_list.hpp
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/unstoppable_token.hpp
Expand Down
4 changes: 3 additions & 1 deletion src/beman/execution26/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

list(APPEND execution_tests
exec-then.pass
exec-just.pass
meta-transform.pass
exec-read-env.pass
exec-get-delegation-scheduler.pass
exec-snd-apply.pass
Expand All @@ -10,7 +13,6 @@ list(APPEND execution_tests
exec-into-variant.pass
exec-run-loop-types.pass
exec-run-loop-general.pass
exec-just.pass
exec-snd-expos.pass
exec-recv-concepts.pass
forward-like.pass
Expand Down
4 changes: 4 additions & 0 deletions src/beman/execution26/tests/exec-just.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,4 +181,8 @@ auto main() -> int
{
test_just_constraints();
test_just();
using type = test_detail::call_result_t<test_std::get_completion_signatures_t,
decltype(test_std::just()), test_std::empty_env>;

static_assert(std::same_as<test_std::completion_signatures<test_std::set_value_t()>, type>);
}
Loading