Skip to content

Commit 422f3ae

Browse files
authored
Merge pull request #20 from beman-project/then
added then, upon_error, upon_stopped algorithms
2 parents 0e281dd + 492348f commit 422f3ae

13 files changed

+479
-22
lines changed

docs/questions.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,5 @@ likely observable.
4242
- [exec.sync_wait] are sync_wait(just_error(17)) and sync_wait(just_stopped())
4343
supposed to work? I don't see a reason why a value completion is necessarily
4444
required. As is, they are not because type_idenity_t ends up being used without
45-
argument.
45+
argument.
46+
- [exec.then] p5 seems to miss a space betweend sendr and out_sndr

include/beman/execution26/detail/basic_sender.hpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -72,25 +72,25 @@ namespace beman::execution26::detail
7272
#if __cpp_explicit_this_parameter < 202110L
7373
template <typename Env>
7474
auto get_completion_signatures(Env&&) &&
75-
-> ::beman::execution26::detail::completion_signatures_for<basic_sender&&, Env>
75+
-> ::beman::execution26::detail::completion_signatures_for<basic_sender, Env>
7676
{
7777
return {};
7878
}
7979
template <typename Env>
8080
auto get_completion_signatures(Env&&) const&&
81-
-> ::beman::execution26::detail::completion_signatures_for<basic_sender const&&, Env>
81+
-> ::beman::execution26::detail::completion_signatures_for<basic_sender, Env>
8282
{
8383
return {};
8484
}
8585
template <typename Env>
8686
auto get_completion_signatures(Env&&) &
87-
-> ::beman::execution26::detail::completion_signatures_for<basic_sender&, Env>
87+
-> ::beman::execution26::detail::completion_signatures_for<basic_sender, Env>
8888
{
8989
return {};
9090
}
9191
template <typename Env>
9292
auto get_completion_signatures(Env&&) const&
93-
-> ::beman::execution26::detail::completion_signatures_for<basic_sender const&, Env>
93+
-> ::beman::execution26::detail::completion_signatures_for<basic_sender, Env>
9494
{
9595
return {};
9696
}

include/beman/execution26/detail/common.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#if defined(__GNUC__)
1010
# pragma GCC diagnostic ignored "-Wmissing-braces"
11+
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
1112
#endif
1213

1314
#if defined(__clang__)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// include/beman/execution26/detail/meta_transform.hpp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_META_TRANSFORM
5+
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_META_TRANSFORM
6+
7+
#include <beman/execution26/detail/meta_contains.hpp>
8+
9+
// ----------------------------------------------------------------------------
10+
11+
namespace beman::execution26::detail::meta::detail
12+
{
13+
template <template <typename> class Transform, typename List> struct transform;
14+
15+
template <template <typename> class Transform,
16+
template <typename... T> class List,
17+
typename... T>
18+
struct transform<Transform, List<T...>>
19+
{
20+
using type = List<Transform<T>...>;
21+
};
22+
}
23+
24+
namespace beman::execution26::detail::meta
25+
{
26+
template <template <typename> class Transform, typename List>
27+
using transform = typename
28+
::beman::execution26::detail::meta::detail::transform<Transform, List>
29+
::type;
30+
}
31+
32+
// ----------------------------------------------------------------------------
33+
34+
#endif

include/beman/execution26/detail/meta_unique.hpp

+21-14
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,35 @@
1313

1414
namespace beman::execution26::detail::meta::detail
1515
{
16+
template <typename, typename> struct make_unique;
1617
template <typename> struct unique;
1718

18-
template <template <typename...> class List>
19-
struct unique<List<>>
19+
template <template <typename...> class List, typename... R>
20+
struct make_unique<List<R...>, List<>>
2021
{
21-
using type = List<>;
22+
using type = List<R...>;
2223
};
23-
template <template <typename...> class List, typename T>
24-
struct unique<List<T>>
24+
25+
template <template <typename...> class List, typename... R, typename H, typename... T>
26+
struct make_unique<List<R...>, List<H, T...>>
2527
{
26-
using type = List<T>;
28+
using type = typename ::beman::execution26::detail::meta::detail::make_unique<
29+
::std::conditional_t<
30+
::beman::execution26::detail::meta::contains<H, R...>,
31+
List<R...>,
32+
List<R..., H>
33+
>,
34+
List<T...>
35+
>::type;
2736
};
2837

29-
template <template <typename...> class List, typename H, typename... T>
30-
struct unique<List<H, T...>>
38+
template <template <typename...> class List, typename... T>
39+
struct unique<List<T...>>
3140
{
32-
using tail = ::beman::execution26::detail::meta::detail::unique<List<T...>>::type;
33-
using type = ::std::conditional_t<
34-
::beman::execution26::detail::meta::contains<H, T...>,
35-
tail,
36-
::beman::execution26::detail::meta::prepend<H, tail>
37-
>;
41+
using type = typename ::beman::execution26::detail::meta::detail::make_unique<
42+
List<>,
43+
List<T...>
44+
>::type;
3845
};
3946
}
4047

include/beman/execution26/detail/sender_adaptor.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ namespace beman::execution26::detail
4242
return apply(::std::forward<Sender>(sender), *this);
4343
}
4444
};
45+
template <typename... T>
46+
sender_adaptor(T&&...) -> sender_adaptor<T...>;
4547
}
4648

4749
// ----------------------------------------------------------------------------
+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
// include/beman/execution26/detail/then.hpp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_THEN
5+
#define INCLUDED_BEMAN_EXECUTION26_DETAIL_THEN
6+
7+
#include <beman/execution26/detail/call_result_t.hpp>
8+
#include <beman/execution26/detail/completion_signatures.hpp>
9+
#include <beman/execution26/detail/completion_signatures_for.hpp>
10+
#include <beman/execution26/detail/completion_signatures_of_t.hpp>
11+
#include <beman/execution26/detail/default_impls.hpp>
12+
#include <beman/execution26/detail/get_domain_early.hpp>
13+
#include <beman/execution26/detail/impls_for.hpp>
14+
#include <beman/execution26/detail/make_sender.hpp>
15+
#include <beman/execution26/detail/meta_transform.hpp>
16+
#include <beman/execution26/detail/meta_unique.hpp>
17+
#include <beman/execution26/detail/movable_value.hpp>
18+
#include <beman/execution26/detail/sender.hpp>
19+
#include <beman/execution26/detail/sender_adaptor.hpp>
20+
#include <beman/execution26/detail/sender_adaptor_closure.hpp>
21+
#include <beman/execution26/detail/set_error.hpp>
22+
#include <beman/execution26/detail/set_stopped.hpp>
23+
#include <beman/execution26/detail/set_value.hpp>
24+
#include <beman/execution26/detail/transform_sender.hpp>
25+
#include <concepts>
26+
#include <exception>
27+
#include <functional>
28+
#include <utility>
29+
30+
// ----------------------------------------------------------------------------
31+
32+
namespace beman::execution26::detail
33+
{
34+
template <typename Completion>
35+
struct then_t
36+
: ::beman::execution26::sender_adaptor_closure<then_t<Completion>>
37+
{
38+
template <::beman::execution26::detail::movable_value Fun>
39+
auto operator()(Fun&& fun) const
40+
{
41+
return ::beman::execution26::detail::sender_adaptor{
42+
*this, ::std::forward<Fun>(fun)
43+
};
44+
}
45+
template <::beman::execution26::sender Sender,
46+
::beman::execution26::detail::movable_value Fun>
47+
auto operator()(Sender&& sender, Fun&& fun) const
48+
{
49+
auto domain{::beman::execution26::detail::get_domain_early(sender)};
50+
return ::beman::execution26::transform_sender(
51+
domain,
52+
::beman::execution26::detail::make_sender(
53+
*this,
54+
::std::forward<Fun>(fun),
55+
::std::forward<Sender>(sender)
56+
)
57+
);
58+
}
59+
};
60+
61+
template <typename Completion>
62+
struct impls_for<then_t<Completion>>
63+
: ::beman::execution26::detail::default_impls
64+
{
65+
static constexpr auto complete
66+
= []<typename Tag, typename... Args>
67+
(auto, auto& fun, auto& receiver, Tag, Args&&... args)
68+
noexcept
69+
-> void
70+
{
71+
if constexpr (::std::same_as<Completion, Tag>)
72+
{
73+
try
74+
{
75+
auto invoke = [&]{
76+
return ::std::invoke(::std::move(fun),
77+
::std::forward<Args>(args)...);
78+
};
79+
if constexpr (::std::same_as<void, decltype(invoke())>)
80+
{
81+
invoke();
82+
::beman::execution26::set_value(
83+
::std::move(receiver)
84+
);
85+
}
86+
else
87+
{
88+
::beman::execution26::set_value(
89+
::std::move(receiver),
90+
invoke()
91+
);
92+
}
93+
}
94+
catch (...)
95+
{
96+
::beman::execution26::set_error(
97+
::std::move(receiver),
98+
::std::current_exception()
99+
);
100+
}
101+
}
102+
else
103+
{
104+
Tag()(::std::move(receiver), ::std::forward<Args>(args)...);
105+
}
106+
};
107+
};
108+
109+
template <typename T>
110+
struct then_set_value
111+
{
112+
using type = ::beman::execution26::set_value_t(T);
113+
};
114+
template <>
115+
struct then_set_value<void>
116+
{
117+
using type = ::beman::execution26::set_value_t();
118+
};
119+
120+
template <typename, typename, typename Completion>
121+
struct then_transform
122+
{
123+
using type = Completion;
124+
};
125+
126+
template <typename Fun, typename Replace>
127+
struct then_transform_t
128+
{
129+
template <typename Completion>
130+
using transform = typename
131+
::beman::execution26::detail::then_transform<Fun, Replace, Completion>
132+
::type;
133+
};
134+
135+
template <typename Fun, typename Completion, typename... T>
136+
struct then_transform<Fun, Completion, Completion(T...)>
137+
{
138+
using type = typename ::beman::execution26::detail::then_set_value<
139+
::beman::execution26::detail::call_result_t<Fun, T...>
140+
>::type;
141+
};
142+
143+
template <typename Completion, typename Fun, typename Sender, typename Env>
144+
struct completion_signatures_for_impl<
145+
::beman::execution26::detail::basic_sender<
146+
::beman::execution26::detail::then_t<Completion>,
147+
Fun,
148+
Sender
149+
>,
150+
Env
151+
>
152+
{
153+
using type = ::beman::execution26::detail::meta::unique<
154+
::beman::execution26::detail::meta::transform<
155+
::beman::execution26::detail::then_transform_t<Fun, Completion>::template transform,
156+
::beman::execution26::completion_signatures_of_t<Sender, Env>
157+
>
158+
>;
159+
};
160+
}
161+
162+
namespace beman::execution26
163+
{
164+
using then_t = ::beman::execution26::detail::then_t<::beman::execution26::set_value_t>;
165+
using upon_error_t = ::beman::execution26::detail::then_t<::beman::execution26::set_error_t>;
166+
using upon_stopped_t = ::beman::execution26::detail::then_t<::beman::execution26::set_stopped_t>;
167+
168+
inline constexpr ::beman::execution26::then_t then{};
169+
inline constexpr ::beman::execution26::upon_error_t upon_error{};
170+
inline constexpr ::beman::execution26::upon_stopped_t upon_stopped{};
171+
}
172+
173+
// ----------------------------------------------------------------------------
174+
175+
#endif

src/beman/execution26/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ target_sources(${TARGET_LIBRARY}
8484
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/meta_contains.hpp
8585
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/meta_filter.hpp
8686
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/meta_prepend.hpp
87+
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/meta_transform.hpp
8788
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/meta_unique.hpp
8889
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/movable_value.hpp
8990
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/never_stop_token.hpp
@@ -123,6 +124,7 @@ target_sources(${TARGET_LIBRARY}
123124
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/stoppable_token.hpp
124125
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/sync_wait.hpp
125126
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/tag_of_t.hpp
127+
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/then.hpp
126128
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/transform_sender.hpp
127129
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/type_list.hpp
128130
${PROJECT_SOURCE_DIR}/include/beman/execution26/detail/unstoppable_token.hpp

src/beman/execution26/tests/CMakeLists.txt

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
33

44
list(APPEND execution_tests
5+
exec-then.pass
6+
exec-just.pass
7+
meta-transform.pass
58
exec-read-env.pass
69
exec-get-delegation-scheduler.pass
710
exec-snd-apply.pass
@@ -10,7 +13,6 @@ list(APPEND execution_tests
1013
exec-into-variant.pass
1114
exec-run-loop-types.pass
1215
exec-run-loop-general.pass
13-
exec-just.pass
1416
exec-snd-expos.pass
1517
exec-recv-concepts.pass
1618
forward-like.pass

src/beman/execution26/tests/exec-just.pass.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -181,4 +181,8 @@ auto main() -> int
181181
{
182182
test_just_constraints();
183183
test_just();
184+
using type = test_detail::call_result_t<test_std::get_completion_signatures_t,
185+
decltype(test_std::just()), test_std::empty_env>;
186+
187+
static_assert(std::same_as<test_std::completion_signatures<test_std::set_value_t()>, type>);
184188
}

0 commit comments

Comments
 (0)