Skip to content

Commit 8c79f51

Browse files
committed
a first version of the async_scope components
1 parent 1a55414 commit 8c79f51

File tree

9 files changed

+558
-299
lines changed

9 files changed

+558
-299
lines changed

include/beman/execution/detail/associate.hpp

Lines changed: 73 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -24,46 +24,40 @@ template <::beman::execution::scope_token Token, ::beman::execution::sender Send
2424
struct associate_data {
2525
using wrap_sender = ::std::remove_cvref_t<decltype(::std::declval<Token&>().wrap(::std::declval<Sender>()))>;
2626

27-
explicit associate_data(Token t, Sender&& s)
28-
: token(t)
29-
, sender(this->token.wrap(::std::forward<Sender>(s)))
30-
{
27+
explicit associate_data(Token t, Sender&& s) : token(t), sender(this->token.wrap(::std::forward<Sender>(s))) {
3128
if (!token.try_associate()) {
3229
this->sender.reset();
3330
}
3431
}
35-
associate_data(associate_data const& other)
36-
noexcept(::std::is_nothrow_copy_constructible_v<wrap_sender> && noexcept(token.try_associate()))
37-
: token(other.token)
38-
, sender()
39-
{
32+
associate_data(const associate_data& other) noexcept(::std::is_nothrow_copy_constructible_v<wrap_sender> &&
33+
noexcept(token.try_associate()))
34+
: token(other.token), sender() {
4035
if (other.sender && this->token.try_associate()) {
41-
try { this->sender.emplace(*other.sender); }
42-
catch (...) { this->token.disassociate(); }
36+
try {
37+
this->sender.emplace(*other.sender);
38+
} catch (...) {
39+
this->token.disassociate();
40+
}
4341
}
4442
}
4543
associate_data(associate_data&& other) noexcept(::std::is_nothrow_move_constructible_v<wrap_sender>)
46-
: token(other.token)
47-
, sender(::std::move(other.sender))
48-
{
44+
: token(other.token), sender(::std::move(other.sender)) {
4945
other.sender.reset();
5046
}
51-
auto operator= (associate_data const&) -> associate_data& = delete;
52-
auto operator= (associate_data &&) -> associate_data& = delete;
47+
auto operator=(const associate_data&) -> associate_data& = delete;
48+
auto operator=(associate_data&&) -> associate_data& = delete;
5349
~associate_data() {
5450
if (this->sender) {
5551
this->sender.reset();
56-
this->token.disassociate();
52+
this->token.disassociate();
5753
}
5854
}
5955

6056
auto release() -> ::std::optional<::std::pair<Token, wrap_sender>> {
61-
return this->sender
62-
? ( std::unique_ptr<std::optional<wrap_sender>, decltype([](auto* opt){ opt->reset(); })>(&this->sender),
63-
::std::optional{::std::pair{::std::move(this->token), ::std::move(*this->sender)}}
64-
)
65-
: ::std::optional<::std::pair<Token, wrap_sender>>{}
66-
;
57+
return this->sender ? (std::unique_ptr<std::optional<wrap_sender>, decltype([](auto* opt) { opt->reset(); })>(
58+
&this->sender),
59+
::std::optional{::std::pair{::std::move(this->token), ::std::move(*this->sender)}})
60+
: ::std::optional<::std::pair<Token, wrap_sender>>{};
6761
}
6862

6963
Token token;
@@ -80,93 +74,82 @@ struct associate_t {
8074
domain,
8175
::beman::execution::detail::make_sender(
8276
*this,
83-
::beman::execution::detail::associate_data(::std::forward<Token>(token), ::std::forward<Sender>(sender))
84-
)
85-
);
77+
::beman::execution::detail::associate_data(::std::forward<Token>(token),
78+
::std::forward<Sender>(sender))));
8679
}
8780
};
8881

8982
template <>
90-
struct impls_for<associate_t>
91-
: ::beman::execution::detail::default_impls {
83+
struct impls_for<associate_t> : ::beman::execution::detail::default_impls {
9284
template <typename, typename>
93-
struct get_noexcept: ::std::false_type {};
85+
struct get_noexcept : ::std::false_type {};
9486
template <typename Tag, typename Data, typename Receiver>
9587
struct get_noexcept<::beman::execution::detail::basic_sender<Tag, Data>, Receiver>
96-
: ::std::bool_constant<
97-
::std::is_nothrow_move_constructible_v<typename ::std::remove_cvref_t<Data>::wrap_sender>
98-
&& ::beman::execution::detail::nothrow_callable<
99-
::beman::execution::connect_t, typename ::std::remove_cvref_t<Data>::wrap_sender, Receiver>
100-
> {};
101-
102-
static constexpr auto get_state = []<typename Sender, typename Receiver>(Sender&& sender, Receiver& receiver)
103-
noexcept(
104-
::std::is_nothrow_constructible_v<::std::remove_cvref_t<Sender>, Sender>
105-
&& get_noexcept<::std::remove_cvref_t<Sender>, Receiver>::value
106-
)
107-
{
108-
auto[_, data] = ::std::forward<Sender>(sender);
109-
auto dataParts{data.release()};
110-
111-
using scope_token = decltype(dataParts->first);
112-
using wrap_sender = decltype(dataParts->second);
113-
using op_t = decltype(::beman::execution::connect(::std::move(dataParts->second), ::std::forward<Receiver>(receiver)));
114-
115-
struct op_state {
116-
bool associated{false};
117-
union {
118-
Receiver* rcvr;
119-
struct {
120-
scope_token tok;
121-
op_t op;
122-
} assoc;
123-
};
124-
explicit op_state(Receiver& r) noexcept: rcvr(::std::addressof(r)) {}
125-
explicit op_state(scope_token tk, wrap_sender&& sndr, Receiver& r)
126-
try
127-
: associated(true)
128-
, assoc(tk, ::beman::execution::connect(::std::move(sndr), ::std::move(r))) {
129-
}
130-
catch (...) {
88+
: ::std::bool_constant<
89+
::std::is_nothrow_move_constructible_v<typename ::std::remove_cvref_t<Data>::wrap_sender>&& ::beman::
90+
execution::detail::nothrow_callable<::beman::execution::connect_t,
91+
typename ::std::remove_cvref_t<Data>::wrap_sender,
92+
Receiver>> {};
93+
94+
static constexpr auto get_state =
95+
[]<typename Sender, typename Receiver>(Sender&& sender, Receiver& receiver) noexcept(
96+
::std::is_nothrow_constructible_v<::std::remove_cvref_t<Sender>, Sender>&&
97+
get_noexcept<::std::remove_cvref_t<Sender>, Receiver>::value) {
98+
auto [_, data] = ::std::forward<Sender>(sender);
99+
auto dataParts{data.release()};
100+
101+
using scope_token = decltype(dataParts->first);
102+
using wrap_sender = decltype(dataParts->second);
103+
using op_t = decltype(::beman::execution::connect(::std::move(dataParts->second),
104+
::std::forward<Receiver>(receiver)));
105+
106+
struct op_state {
107+
using sop_t = op_t;
108+
using sscope_token = scope_token;
109+
bool associated{false};
110+
union {
111+
Receiver* rcvr;
112+
struct {
113+
sscope_token tok;
114+
sop_t op;
115+
} assoc;
116+
};
117+
explicit op_state(Receiver& r) noexcept : rcvr(::std::addressof(r)) {}
118+
explicit op_state(sscope_token tk, wrap_sender&& sndr, Receiver& r) try
119+
: associated(true), assoc(tk, ::beman::execution::connect(::std::move(sndr), ::std::move(r))) {
120+
} catch (...) {
131121
tk.disassociate();
132122
throw;
133123
}
134-
op_state(op_state&&) = delete;
135-
~op_state() {
136-
if (this->associated) {
137-
this->assoc.op.~op_t();
138-
this->assoc.tok.disassociate();
139-
this->assoc.tok.~scope_token();
140-
}
141-
}
142-
auto run() noexcept -> void {
143-
if (this->associated) {
144-
::beman::execution::start(this->assoc.op);
124+
op_state(op_state&&) = delete;
125+
~op_state() {
126+
if (this->associated) {
127+
this->assoc.op.~sop_t();
128+
this->assoc.tok.disassociate();
129+
this->assoc.tok.~sscope_token();
130+
}
145131
}
146-
else {
147-
::beman::execution::set_stopped(::std::move(*this->rcvr));
132+
auto run() noexcept -> void {
133+
if (this->associated) {
134+
::beman::execution::start(this->assoc.op);
135+
} else {
136+
::beman::execution::set_stopped(::std::move(*this->rcvr));
137+
}
148138
}
149-
}
139+
};
140+
return dataParts ? op_state(::std::move(dataParts->first), ::std::move(dataParts->second), receiver)
141+
: op_state(receiver);
150142
};
151-
return dataParts
152-
? op_state(::std::move(dataParts->first), ::std::move(dataParts->second), receiver)
153-
: op_state(receiver)
154-
;
155-
};
156-
static constexpr auto start = [](auto& state, auto&&) noexcept -> void{
157-
state.run();
158-
};
143+
static constexpr auto start = [](auto& state, auto&&) noexcept -> void { state.run(); };
159144
};
160145

161146
template <typename Data, typename Env>
162147
struct completion_signatures_for_impl<
163148
::beman::execution::detail::basic_sender<::beman::execution::detail::associate_t, Data>,
164149
Env> {
165-
using type = ::beman::execution::completion_signatures<
166-
::beman::execution::set_value_t()
167-
>;
150+
using type = ::beman::execution::completion_signatures<::beman::execution::set_value_t()>;
168151
};
169-
}
152+
} // namespace beman::execution::detail
170153

171154
namespace beman::execution {
172155
using associate_t = ::beman::execution::detail::associate_t;
Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,60 @@
11
// include/beman/execution/detail/counting_scope.hpp -*-C++-*-
2-
// ----------------------------------------------------------------------------
32
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4-
// ----------------------------------------------------------------------------
53

64
#ifndef INCLUDED_INCLUDE_BEMAN_EXECUTION_DETAIL_COUNTING_SCOPE
75
#define INCLUDED_INCLUDE_BEMAN_EXECUTION_DETAIL_COUNTING_SCOPE
86

7+
#include <beman/execution/detail/counting_scope_base.hpp>
8+
#include <beman/execution/detail/counting_scope_join.hpp>
9+
#include <beman/execution/detail/sender.hpp>
10+
#include <beman/execution/detail/inplace_stop_source.hpp>
11+
#include <beman/execution/detail/stop_when.hpp>
12+
#include <utility>
13+
#include <cstdlib>
14+
915
// ----------------------------------------------------------------------------
1016

11-
namespace nstd {
12-
namespace xxx {}
13-
} // namespace nstd
17+
namespace beman::execution {
18+
class counting_scope;
19+
}
1420

1521
// ----------------------------------------------------------------------------
1622

23+
class beman::execution::counting_scope : public ::beman::execution::detail::counting_scope_base {
24+
public:
25+
class token;
26+
27+
auto join() noexcept -> ::beman::execution::sender auto {
28+
return ::beman::execution::detail::counting_scope_join(this);
29+
}
30+
auto get_token() noexcept -> token;
31+
auto request_stop() noexcept -> void { this->stop_source.request_stop(); }
32+
33+
private:
34+
::beman::execution::inplace_stop_source stop_source{};
35+
};
36+
37+
// ----------------------------------------------------------------------------
38+
39+
class beman::execution::counting_scope::token : public ::beman::execution::detail::counting_scope_base::token {
40+
public:
41+
template <::beman::execution::sender Sender>
42+
auto wrap(Sender&& sender) const noexcept -> ::beman::execution::sender auto {
43+
return ::beman::execution::detail::stop_when(
44+
::std::forward<Sender>(sender),
45+
static_cast<::beman::execution::counting_scope*>(this->scope)->stop_source.get_token());
46+
}
47+
48+
private:
49+
friend class beman::execution::counting_scope;
50+
explicit token(::beman::execution::counting_scope* s)
51+
: ::beman::execution::detail::counting_scope_base::token(s) {}
52+
};
53+
54+
// ----------------------------------------------------------------------------
55+
56+
inline auto beman::execution::counting_scope::get_token() noexcept -> beman::execution::counting_scope::token {
57+
return beman::execution::counting_scope::token(this);
58+
}
59+
1760
#endif

0 commit comments

Comments
 (0)