Skip to content

Commit d6271ce

Browse files
committed
added a sender example printing completion signatures
1 parent d2ac62b commit d6271ce

File tree

13 files changed

+225
-6
lines changed

13 files changed

+225
-6
lines changed

examples/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
list(
77
APPEND
88
EXAMPLES
9+
inspect
910
playground
1011
sender-demo
1112
when_all-cancel

examples/inspect.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// examples/inspectc.pp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#include <beman/execution/execution.hpp>
5+
#include "meta.hpp"
6+
#include <iostream>
7+
#include <sstream>
8+
#include <typeinfo>
9+
10+
namespace ex = beman::execution;
11+
12+
// ----------------------------------------------------------------------------
13+
14+
namespace {
15+
struct logger_t {
16+
template <ex::sender Sndr, ex::receiver Rcvr, typename Log>
17+
struct state {
18+
using operation_state_concept = ex::operation_state_t;
19+
using inner_t = decltype(ex::connect(std::declval<Sndr>(), std::declval<Rcvr>()));
20+
21+
inner_t inner;
22+
std::remove_cvref_t<Log> log;
23+
state(Sndr&& s, Rcvr&& r, Log&& l)
24+
: inner(ex::connect(std::forward<Sndr>(s), std::forward<Rcvr>(r))), log(std::forward<Log>(l)) {}
25+
auto start() & noexcept -> void {
26+
this->log(meta::type<decltype(ex::get_completion_signatures(std::declval<Sndr>(),
27+
ex::get_env(std::declval<Rcvr>())))>::name());
28+
ex::start(this->inner);
29+
}
30+
};
31+
32+
template <ex::sender Sndr, typename Log>
33+
struct sender {
34+
using sender_concept = ex::sender_t;
35+
36+
Sndr sndr;
37+
Log log;
38+
39+
template <typename Env>
40+
auto get_completion_signatures(const Env& env) const noexcept {
41+
return ex::get_completion_signatures(this->sndr, env);
42+
}
43+
44+
template <ex::receiver Receiver>
45+
auto connect(Receiver&& receiver) && noexcept(noexcept(ex::connect(std::move(this->sndr),
46+
std::forward<Receiver>(receiver)))) {
47+
return state<Sndr, Receiver, Log>(
48+
std::move(this->sndr), std::forward<Receiver>(receiver), std::move(this->log));
49+
}
50+
};
51+
52+
template <ex::sender Sndr, typename Log>
53+
auto operator()(Sndr&& sndr, Log&& log) const {
54+
return sender<std::remove_cvref_t<Sndr>, std::remove_cvref_t<Log>>{std::forward<Sndr>(sndr),
55+
std::forward<Log>(log)};
56+
}
57+
};
58+
59+
inline constexpr logger_t logger{};
60+
} // namespace
61+
62+
// ----------------------------------------------------------------------------
63+
64+
int main() {
65+
auto log = [](std::string_view name) {
66+
return [name](std::string_view msg) { std::cout << name << " message='" << msg << "'\n"; };
67+
};
68+
69+
ex::sync_wait(logger(ex::just(), log("just()")));
70+
ex::sync_wait(logger(ex::just() | ex::then([]() {}), log("just() | then(...)")));
71+
ex::sync_wait(logger(ex::just() | ex::then([]() noexcept {}), log("just() | then(...)")));
72+
ex::sync_wait(logger(ex::just(0, 1), log("just(0, 1)")));
73+
ex::sync_wait(logger(ex::just(0, 1, 2), log("just(0, 1, 2)")));
74+
ex::sync_wait(logger(ex::just_error(0), log("just_error(0)")) | ex::upon_error([](auto) {}));
75+
ex::sync_wait(logger(ex::just_stopped(), log("just_stopped()")) | ex::upon_stopped([]() {}));
76+
}

examples/intro-1-hello-world.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ int main() {
1818
ex::when_all(
1919
ex::just("hello, "s),
2020
ex::just("world"s)
21-
) | ex::then([](auto s1, auto s2) { return s1 + s2; })
21+
) | ex::then([](auto const& s1, auto const& s2) { return s1 + s2; })
2222
).value_or(std::tuple(""s)
2323
);
2424
// clang-format on

examples/intro-2-hello-async.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ int main() {
3030
| ex::then([] { std::cout << ",\n"; return std::string(", "); }),
3131
timer.resume_after(2s)
3232
| ex::then([] { std::cout << "w\n"; return std::string("world"); })
33-
) | ex::then([](auto s1, auto s2, auto s3) { return s1 + s2 + s3; })
33+
) | ex::then([](auto const& s1, auto const& s2, auto const& s3) { return s1 + s2 + s3; })
3434
)
3535
).value_or(std::tuple(std::string("")));
3636
// clang-format on

examples/intro-5-consumer.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
#include <iostream>
88
#include <string>
99
#include <tuple>
10+
#include <cinttypes>
1011

1112
namespace ex = ::beman::execution;
1213
using namespace std::string_literals;
1314

14-
enum class success { one };
15-
enum class failure { fail_one };
15+
enum class success : std::uint8_t { one };
16+
enum class failure : std::uint8_t { fail_one };
1617

1718
struct expected_to_channel_t {
1819
template <typename Receiver>

examples/meta.hpp

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// examples/meta.hpp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#ifndef INCLUDED_EXAMPLES_META
5+
#define INCLUDED_EXAMPLES_META
6+
7+
#include <beman/execution/execution.hpp>
8+
#include <ostream>
9+
#include <string>
10+
#include <typeinfo>
11+
12+
// ----------------------------------------------------------------------------
13+
14+
namespace meta {
15+
// The code in this namespace is a fairly basic way to print types. It can
16+
// almost certainly be done better, in particular using reflection. However,
17+
// that's beside the point of this example. The important part for the
18+
// example is that meta::type<T>::name() yields a string representing the
19+
// type T in some reasonable way
20+
template <template <typename...> class, typename...>
21+
struct list {
22+
static auto name() { return "unknown-list"; }
23+
};
24+
template <>
25+
struct list<::beman::execution::completion_signatures> {
26+
static auto name() { return "ex::completion_signatures"; }
27+
};
28+
29+
template <typename T>
30+
struct type {
31+
static auto name() { return typeid(T).name(); }
32+
};
33+
template <typename T>
34+
struct type<T&> {
35+
static auto name() { return typeid(T).name() + std::string("&"); }
36+
};
37+
template <typename T>
38+
struct type<T&&> {
39+
static auto name() { return typeid(T).name() + std::string("&&"); }
40+
};
41+
template <typename T>
42+
struct type<T*> {
43+
static auto name() { return typeid(T).name() + std::string("*"); }
44+
};
45+
template <typename T>
46+
struct type<const T> {
47+
static auto name() { return typeid(T).name() + std::string("const"); }
48+
};
49+
template <typename T>
50+
struct type<volatile T> {
51+
static auto name() { return typeid(T).name() + std::string("volatile"); }
52+
};
53+
template <typename T>
54+
struct type<const volatile T> {
55+
static auto name() { return typeid(T).name() + std::string("const volatile"); }
56+
};
57+
// NOLINTBEGIN(hicpp-avoid-c-arrays)
58+
template <typename T, std::size_t N>
59+
struct type<T[N]> {
60+
static auto name() { return typeid(T).name() + std::string("[") + std::to_string(N) + "]"; }
61+
};
62+
template <typename T, std::size_t N>
63+
struct type<T (&)[N]> {
64+
static auto name() { return typeid(T).name() + std::string("(&)[") + std::to_string(N) + "]"; }
65+
};
66+
template <typename T, std::size_t N>
67+
struct type<T (*)[N]> {
68+
static auto name() { return typeid(T).name() + std::string("(*)[") + std::to_string(N) + "]"; }
69+
};
70+
// NOLINTEND(hicpp-avoid-c-arrays)
71+
72+
template <>
73+
struct type<::beman::execution::set_value_t> {
74+
static auto name() { return "ex::set_value_t"; }
75+
};
76+
template <>
77+
struct type<::beman::execution::set_error_t> {
78+
static auto name() { return "ex::set_error_t"; }
79+
};
80+
template <>
81+
struct type<::beman::execution::set_stopped_t> {
82+
static auto name() { return "ex::set_stopped_t"; }
83+
};
84+
85+
template <typename T>
86+
struct type<T()> {
87+
static auto name() { return type<T>::name() + std::string("()"); }
88+
};
89+
template <typename T, typename A, typename... B>
90+
struct type<T(A, B...)> {
91+
static auto name() {
92+
return type<T>::name() + std::string("(") + (type<A>::name() + ... + (std::string(", ") + type<B>::name())) +
93+
")";
94+
}
95+
};
96+
template <typename T>
97+
struct type<T (*)()> {
98+
static auto name() { return type<T>::name() + std::string("(*)()"); }
99+
};
100+
template <typename T, typename A, typename... B>
101+
struct type<T (*)(A, B...)> {
102+
static auto name() {
103+
return type<T>::name() + std::string("(*)(") +
104+
(type<A>::name() + ... + (std::string(", ") + type<B>::name())) + ")";
105+
}
106+
};
107+
108+
template <template <typename...> class L>
109+
struct type<L<>> {
110+
static auto name() { return list<L>::name() + std::string("<>"); }
111+
};
112+
113+
template <template <typename...> class L, typename T, typename... S>
114+
struct type<L<T, S...>> {
115+
static auto name() {
116+
return list<L>::name() + std::string("<") + (type<T>::name() + ... + (std::string(", ") + type<S>::name())) +
117+
">";
118+
}
119+
};
120+
121+
template <typename T>
122+
inline std::ostream& operator<<(std::ostream& out, const type<T>& t) {
123+
return out << t.name();
124+
}
125+
} // namespace meta
126+
127+
// ----------------------------------------------------------------------------
128+
129+
#endif

include/beman/execution/detail/basic_state.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <beman/execution/detail/sender_decompose.hpp>
99
#include <beman/execution/detail/tag_of_t.hpp>
1010
#include <beman/execution/detail/state_type.hpp>
11+
#include <exception>
1112
#include <utility>
1213

1314
// ----------------------------------------------------------------------------

include/beman/execution/detail/product_type.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ constexpr auto is_product_type(const ::beman::execution::detail::product_type<T.
114114

115115
template <::std::size_t Start, typename Fun, typename Tuple, ::std::size_t... I>
116116
constexpr auto sub_apply_helper(Fun&& fun, Tuple&& tuple, ::std::index_sequence<I...>) -> decltype(auto) {
117+
// NOLINTNEXTLINE(bugprone-use-after-move,hicpp-invalid-access-moved)
117118
return ::std::forward<Fun>(fun)(::std::forward<Tuple>(tuple).template get<I + Start>()...);
118119
}
119120

include/beman/execution/detail/run_loop.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class run_loop {
5050
run_loop* loop;
5151
Receiver receiver;
5252

53+
// NOLINTBEGIN(misc-no-recursion)
5354
template <typename R>
5455
opstate(run_loop* l, R&& rcvr) : loop(l), receiver(::std::forward<Receiver>(rcvr)) {}
5556
auto start() & noexcept -> void {
@@ -59,6 +60,7 @@ class run_loop {
5960
::beman::execution::set_error(::std::move(this->receiver), ::std::current_exception());
6061
}
6162
}
63+
// NOLINTEND(misc-no-recursion)
6264
auto execute() noexcept -> void override {
6365
if (::beman::execution::get_stop_token(::beman::execution::get_env(this->receiver)).stop_requested())
6466
::beman::execution::set_stopped(::std::move(this->receiver));

include/beman/execution/detail/set_error.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@ struct set_error_t {
3434
auto operator()(Receiver&&, Error&&) const
3535
-> void = BEMAN_EXECUTION_DELETE("the call to receiver.set_error(error) has to be noexcept");
3636

37+
// NOLINTBEGIN(misc-no-recursion)
3738
template <typename Receiver, typename Error>
3839
auto operator()(Receiver&& receiver, Error&& error) const noexcept -> void {
3940
::std::forward<Receiver>(receiver).set_error(::std::forward<Error>(error));
4041
}
42+
// NOLINTEND(misc-no-recursion)
4143
};
4244

4345
/*!

0 commit comments

Comments
 (0)