Skip to content

Commit 54e9cc9

Browse files
committed
added stop_when
1 parent d5a84cf commit 54e9cc9

File tree

13 files changed

+530
-218
lines changed

13 files changed

+530
-218
lines changed

include/beman/execution/detail/as_tuple.hpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,16 @@
99
// ----------------------------------------------------------------------------
1010

1111
namespace beman::execution::detail {
12-
template <typename T> struct as_tuple;
13-
template <typename Rc, typename... A>
14-
struct as_tuple<Rc(A...)> { using type = ::beman::execution::detail::decayed_tuple<Rc, A...>; };
12+
template <typename T>
13+
struct as_tuple;
14+
template <typename Rc, typename... A>
15+
struct as_tuple<Rc(A...)> {
16+
using type = ::beman::execution::detail::decayed_tuple<Rc, A...>;
17+
};
1518

16-
template <typename T> using as_tuple_t = typename ::beman::execution::detail::as_tuple<T>::type;
17-
}
19+
template <typename T>
20+
using as_tuple_t = typename ::beman::execution::detail::as_tuple<T>::type;
21+
} // namespace beman::execution::detail
1822

1923
// ----------------------------------------------------------------------------
2024

include/beman/execution/detail/counting_scope.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@
99
// ----------------------------------------------------------------------------
1010

1111
namespace nstd {
12-
namespace xxx {
13-
}
14-
}
12+
namespace xxx {}
13+
} // namespace nstd
1514

1615
// ----------------------------------------------------------------------------
1716

include/beman/execution/detail/prop.hpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@
99
// ----------------------------------------------------------------------------
1010

1111
namespace beman::execution {
12-
template <typename Query, typename Value>
13-
struct prop {
14-
[[no_unique_address]] Query query_;
15-
Value value_;
12+
template <typename Query, typename Value>
13+
struct prop {
14+
[[no_unique_address]] Query query_;
15+
Value value_;
1616

17-
auto operator=(prop const&) = delete;
17+
auto operator=(const prop&) = delete;
1818

19-
constexpr auto query(Query) const noexcept -> Value { return this->value_; }
20-
};
19+
constexpr auto query(Query) const noexcept -> Value { return this->value_; }
20+
};
2121

22-
template <typename Query, typename Value>
23-
prop(Query, Value) -> prop<Query, ::std::unwrap_reference_t<Value>>;
24-
}
22+
template <typename Query, typename Value>
23+
prop(Query, Value) -> prop<Query, ::std::unwrap_reference_t<Value>>;
24+
} // namespace beman::execution
2525

2626
// ----------------------------------------------------------------------------
2727

include/beman/execution/detail/spawn.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@
99
// ----------------------------------------------------------------------------
1010

1111
namespace nstd {
12-
namespace xxx {
13-
}
14-
}
12+
namespace xxx {}
13+
} // namespace nstd
1514

1615
// ----------------------------------------------------------------------------
1716

include/beman/execution/detail/spawn_future.hpp

Lines changed: 64 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -23,79 +23,81 @@
2323
// ----------------------------------------------------------------------------
2424

2525
namespace beman::execution::detail {
26-
template <typename> struct non_throwing_args_copy;
27-
template <typename Rc, typename... A> struct non_throwing_args_copy<Rc(A...)> {
28-
static constexpr bool value = (true && ... && ::std::is_nothrow_constructible_v<::std::decay_t<A>, A> );
29-
};
30-
template <typename S> inline constexpr bool non_throwing_args_copy_v{non_throwing_args_copy<S>::value};
26+
template <typename>
27+
struct non_throwing_args_copy;
28+
template <typename Rc, typename... A>
29+
struct non_throwing_args_copy<Rc(A...)> {
30+
static constexpr bool value = (true && ... && ::std::is_nothrow_constructible_v<::std::decay_t<A>, A>);
31+
};
32+
template <typename S>
33+
inline constexpr bool non_throwing_args_copy_v{non_throwing_args_copy<S>::value};
3134

32-
template <typename Completions> struct spawn_future_state_base;
33-
template <typename... Sigs>
34-
struct spawn_future_state_base<::beman::execution::completion_signatures<Sigs...>> {
35-
static constexpr bool has_non_throwing_args_copy = (true && ... && non_throwing_args_copy_v<Sigs>);
36-
using variant_t = ::beman::execution::detail::meta::unique<
37-
::std::conditional_t<
38-
has_non_throwing_args_copy,
39-
::std::variant<::std::monostate, ::beman::execution::detail::as_tuple_t<Sigs>...>,
40-
::std::variant<::std::monostate, ::std::tuple<::beman::execution::set_error_t, ::std::exception_ptr>, ::beman::execution::detail::as_tuple_t<Sigs>...>
41-
>
42-
>;
35+
template <typename Completions>
36+
struct spawn_future_state_base;
37+
template <typename... Sigs>
38+
struct spawn_future_state_base<::beman::execution::completion_signatures<Sigs...>> {
39+
static constexpr bool has_non_throwing_args_copy = (true && ... && non_throwing_args_copy_v<Sigs>);
40+
using variant_t = ::beman::execution::detail::meta::unique<
41+
::std::conditional_t<has_non_throwing_args_copy,
42+
::std::variant<::std::monostate, ::beman::execution::detail::as_tuple_t<Sigs>...>,
43+
::std::variant<::std::monostate,
44+
::std::tuple<::beman::execution::set_error_t, ::std::exception_ptr>,
45+
::beman::execution::detail::as_tuple_t<Sigs>...>>>;
4346

44-
variant_t result{};
45-
virtual ~spawn_future_state_base() = default;
46-
virtual auto complete() noexcept -> void = 0;
47-
};
47+
variant_t result{};
48+
virtual ~spawn_future_state_base() = default;
49+
virtual auto complete() noexcept -> void = 0;
50+
};
4851

49-
template <typename Completions>
50-
struct spawn_future_receiver {
51-
using receiver_concept = ::beman::execution::receiver_t;
52-
using state_t = ::beman::execution::detail::spawn_future_state_base<Completions>;
52+
template <typename Completions>
53+
struct spawn_future_receiver {
54+
using receiver_concept = ::beman::execution::receiver_t;
55+
using state_t = ::beman::execution::detail::spawn_future_state_base<Completions>;
5356

54-
state_t* state{};
57+
state_t* state{};
5558

56-
template <typename... A>
57-
auto set_value(A&&... a) && noexcept -> void {
58-
this->set_complete<::beman::execution::set_value_t>(::std::forward<A>(a)...);
59-
}
60-
template <typename E>
61-
auto set_error(E&& e) && noexcept -> void {
62-
this->set_complete<::beman::execution::set_error_t>(::std::forward<E>(e));
63-
}
64-
auto set_stopped() && noexcept -> void {
65-
this->set_complete<::beman::execution::set_stopped_t>();
66-
}
59+
template <typename... A>
60+
auto set_value(A&&... a) && noexcept -> void {
61+
this->set_complete<::beman::execution::set_value_t>(::std::forward<A>(a)...);
62+
}
63+
template <typename E>
64+
auto set_error(E&& e) && noexcept -> void {
65+
this->set_complete<::beman::execution::set_error_t>(::std::forward<E>(e));
66+
}
67+
auto set_stopped() && noexcept -> void { this->set_complete<::beman::execution::set_stopped_t>(); }
6768

68-
template <typename Tag, typename... T>
69-
auto set_complete(T&&... t) noexcept {
70-
try {
71-
this->state->result.template emplace<::beman::execution::detail::decayed_tuple<Tag, T...>>(Tag(), ::std::forward<T>(t)...);
69+
template <typename Tag, typename... T>
70+
auto set_complete(T&&... t) noexcept {
71+
try {
72+
this->state->result.template emplace<::beman::execution::detail::decayed_tuple<Tag, T...>>(
73+
Tag(), ::std::forward<T>(t)...);
74+
} catch (...) {
75+
if constexpr (!state_t::has_non_throwing_args_copy) {
76+
this->state->result
77+
.template emplace<::std::tuple<::beman::execution::set_error_t, ::std::exception_ptr>>(
78+
::beman::execution::set_error_t{}, ::std::current_exception());
7279
}
73-
catch (...) {
74-
if constexpr (!state_t::has_non_throwing_args_copy) {
75-
this->state->result.template emplace<::std::tuple<::beman::execution::set_error_t, ::std::exception_ptr>>(::beman::execution::set_error_t{}, ::std::current_exception());
76-
}
77-
}
78-
this->state->complete();
7980
}
80-
};
81+
this->state->complete();
82+
}
83+
};
8184

82-
class spawn_future_t {
83-
public:
84-
template <::beman::execution::sender Sndr, ::beman::execution::async_scope_token Tok, typename Env>
85-
requires ::beman::execution::detail::queryable<::std::remove_cvref_t<Env>>
86-
auto operator()(Sndr&&, Tok&&, Env&&) const {
87-
}
88-
template <::beman::execution::sender Sndr, ::beman::execution::async_scope_token Tok>
89-
auto operator()(Sndr&& sndr, Tok&& tok) const {
90-
return (*this)(::std::forward<Sndr>(sndr), ::std::forward<Tok>(tok), ::beman::execution::empty_env{});
91-
}
92-
};
93-
}
85+
class spawn_future_t {
86+
public:
87+
template <::beman::execution::sender Sndr, ::beman::execution::async_scope_token Tok, typename Env>
88+
requires ::beman::execution::detail::queryable<::std::remove_cvref_t<Env>>
89+
auto operator()(Sndr&&, Tok&&, Env&&) const {}
90+
template <::beman::execution::sender Sndr, ::beman::execution::async_scope_token Tok>
91+
auto operator()(Sndr&& sndr, Tok&& tok) const {
92+
return (*this)(::std::forward<Sndr>(sndr), ::std::forward<Tok>(tok), ::beman::execution::empty_env{});
93+
}
94+
};
95+
} // namespace beman::execution::detail
9496

9597
namespace beman::execution {
96-
using spawn_future_t = ::beman::execution::detail::spawn_future_t;
97-
inline constexpr spawn_future_t spawn_future{};
98-
}
98+
using spawn_future_t = ::beman::execution::detail::spawn_future_t;
99+
inline constexpr spawn_future_t spawn_future{};
100+
} // namespace beman::execution
99101

100102
// ----------------------------------------------------------------------------
101103

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
// include/beman/execution/detail/stop_when.hpp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#ifndef INCLUDED_INCLUDE_BEMAN_EXECUTION_DETAIL_STOP_WHEN
5+
#define INCLUDED_INCLUDE_BEMAN_EXECUTION_DETAIL_STOP_WHEN
6+
7+
#include <beman/execution/detail/sender.hpp>
8+
#include <beman/execution/detail/receiver.hpp>
9+
#include <beman/execution/detail/stoppable_token.hpp>
10+
#include <beman/execution/detail/unstoppable_token.hpp>
11+
#include <beman/execution/detail/inplace_stop_source.hpp>
12+
#include <beman/execution/detail/operation_state.hpp>
13+
#include <beman/execution/detail/get_stop_token.hpp>
14+
#include <beman/execution/detail/get_env.hpp>
15+
#include <beman/execution/detail/start.hpp>
16+
#include <beman/execution/detail/set_value.hpp>
17+
#include <beman/execution/detail/set_error.hpp>
18+
#include <beman/execution/detail/set_stopped.hpp>
19+
#include <beman/execution/detail/get_completion_signatures.hpp>
20+
#include <beman/execution/detail/connect.hpp>
21+
#include <beman/execution/detail/stop_callback_for_t.hpp>
22+
#include <type_traits>
23+
#include <optional>
24+
#include <utility>
25+
26+
// ----------------------------------------------------------------------------
27+
28+
namespace beman::execution::detail {
29+
inline constexpr struct stop_when_t {
30+
31+
template <::beman::execution::sender Sndr, ::beman::execution::stoppable_token Tok>
32+
struct sender {
33+
using sender_concept = ::beman::execution::sender_t;
34+
35+
std::remove_cvref_t<Sndr> sndr;
36+
std::remove_cvref_t<Tok> tok;
37+
38+
template <::beman::execution::receiver Rcvr>
39+
struct state {
40+
using operation_state_concept = ::beman::execution::operation_state_t;
41+
using rcvr_t = ::std::remove_cvref_t<Rcvr>;
42+
using token1_t = ::std::remove_cvref_t<Tok>;
43+
using token2_t =
44+
decltype(::beman::execution::get_stop_token(::beman::execution::get_env(::std::declval<rcvr_t>())));
45+
46+
struct cb_t {
47+
::beman::execution::inplace_stop_source& source;
48+
auto operator()() const noexcept { this->source.request_stop(); }
49+
};
50+
struct base_state {
51+
rcvr_t rcvr;
52+
::beman::execution::inplace_stop_source source{};
53+
};
54+
struct env {
55+
base_state* st;
56+
auto query(const ::beman::execution::get_stop_token_t&) const noexcept {
57+
return this->st->source.get_token();
58+
}
59+
template <typename Q, typename... A>
60+
requires requires(const Q& q, A&&... a, const rcvr_t& r) {
61+
q(::beman::execution::get_env(r), ::std::forward<A>(a)...);
62+
}
63+
auto query(const Q& q, A&&... a) const noexcept {
64+
return q(::beman::execution::get_env(this->st->rcvr), ::std::forward<A>(a)...);
65+
}
66+
};
67+
68+
struct receiver {
69+
using receiver_concept = ::beman::execution::receiver_t;
70+
base_state* st;
71+
72+
auto get_env() const noexcept -> env { return env{this->st}; }
73+
template <typename... A>
74+
auto set_value(A&&... a) const noexcept -> void {
75+
::beman::execution::set_value(::std::move(this->st->rcvr), ::std::forward<A>(a)...);
76+
}
77+
template <typename E>
78+
auto set_error(E&& e) const noexcept -> void {
79+
::beman::execution::set_error(::std::move(this->st->rcvr), ::std::forward<E>(e));
80+
}
81+
auto set_stopped() const noexcept -> void {
82+
::beman::execution::set_stopped(::std::move(this->st->rcvr));
83+
}
84+
};
85+
using inner_state_t =
86+
decltype(::beman::execution::connect(::std::declval<Sndr>(), ::std::declval<receiver>()));
87+
88+
token1_t tok;
89+
base_state base;
90+
std::optional<::beman::execution::stop_callback_for_t<token1_t, cb_t>> cb1;
91+
std::optional<::beman::execution::stop_callback_for_t<token2_t, cb_t>> cb2;
92+
inner_state_t inner_state;
93+
94+
template <::beman::execution::sender S,
95+
::beman::execution::stoppable_token T,
96+
::beman::execution::receiver R>
97+
state(S&& s, T&& t, R&& r)
98+
: tok(::std::forward<T>(t)),
99+
base{::std::forward<R>(r)},
100+
inner_state(::beman::execution::connect(::std::forward<S>(s), receiver(&this->base))) {}
101+
102+
auto start() & noexcept {
103+
this->cb1.emplace(this->tok, cb_t(this->base.source));
104+
this->cb2.emplace(::beman::execution::get_stop_token(::beman::execution::get_env(this->base.rcvr)),
105+
cb_t(this->base.source));
106+
::beman::execution::start(this->inner_state);
107+
}
108+
};
109+
110+
template <typename E>
111+
auto get_completion_signatures(const E& e) const noexcept {
112+
return ::beman::execution::get_completion_signatures(this->sndr, e);
113+
}
114+
template <::beman::execution::receiver Rcvr>
115+
auto connect(Rcvr&& rcvr) && -> state<Rcvr> {
116+
return state<Rcvr>{std::move(this->sndr), ::std::move(this->tok), ::std::forward<Rcvr>(rcvr)};
117+
}
118+
};
119+
120+
template <::beman::execution::sender Sndr, ::beman::execution::stoppable_token Tok>
121+
auto operator()(Sndr&& sndr, Tok&& tok) const noexcept {
122+
if constexpr (::beman::execution::unstoppable_token<Tok>) {
123+
return ::std::forward<Sndr>(sndr);
124+
} else {
125+
return sender<Sndr, Tok>(::std::forward<Sndr>(sndr), ::std::forward<Tok>(tok));
126+
}
127+
}
128+
} stop_when{};
129+
} // namespace beman::execution::detail
130+
131+
// ----------------------------------------------------------------------------
132+
133+
#endif

include/beman/execution/execution.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include <beman/execution/detail/just.hpp>
4444
#include <beman/execution/detail/let.hpp>
4545
#include <beman/execution/detail/on.hpp>
46+
#include <beman/execution/detail/prop.hpp>
4647
#include <beman/execution/detail/read_env.hpp>
4748
#include <beman/execution/detail/schedule_from.hpp>
4849
#include <beman/execution/detail/starts_on.hpp>

src/beman/execution/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ target_sources(
173173
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/stop_callback_for_t.hpp
174174
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/stop_source.hpp
175175
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/stop_token_of_t.hpp
176+
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/stop_when.hpp
176177
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/stoppable_source.hpp
177178
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/stoppable_token.hpp
178179
${PROJECT_SOURCE_DIR}/include/beman/execution/detail/suppress_pop.hpp

tests/beman/execution/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ endif()
1111
list(
1212
APPEND
1313
execution_tests
14+
exec-stop-when.test
1415
exec-prop.test
1516
exec-scope-simple-counting.test
1617
exec-spawn-future.test

0 commit comments

Comments
 (0)