Skip to content
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
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
list(
APPEND
EXAMPLES
inspect
playground
sender-demo
when_all-cancel
Expand Down
76 changes: 76 additions & 0 deletions examples/inspect.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// examples/inspectc.pp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <beman/execution/execution.hpp>
#include "meta.hpp"
#include <iostream>
#include <sstream>
#include <typeinfo>

namespace ex = beman::execution;

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

namespace {
struct logger_t {
template <ex::sender Sndr, ex::receiver Rcvr, typename Log>
struct state {
using operation_state_concept = ex::operation_state_t;
using inner_t = decltype(ex::connect(std::declval<Sndr>(), std::declval<Rcvr>()));

inner_t inner;
std::remove_cvref_t<Log> log;
state(Sndr&& s, Rcvr&& r, Log&& l)
: inner(ex::connect(std::forward<Sndr>(s), std::forward<Rcvr>(r))), log(std::forward<Log>(l)) {}
auto start() & noexcept -> void {
this->log(meta::type<decltype(ex::get_completion_signatures(std::declval<Sndr>(),
ex::get_env(std::declval<Rcvr>())))>::name());
ex::start(this->inner);
}
};

template <ex::sender Sndr, typename Log>
struct sender {
using sender_concept = ex::sender_t;

Sndr sndr;
Log log;

template <typename Env>
auto get_completion_signatures(const Env& env) const noexcept {
return ex::get_completion_signatures(this->sndr, env);
}

template <ex::receiver Receiver>
auto connect(Receiver&& receiver) && noexcept(noexcept(ex::connect(std::move(this->sndr),
std::forward<Receiver>(receiver)))) {
return state<Sndr, Receiver, Log>(
std::move(this->sndr), std::forward<Receiver>(receiver), std::move(this->log));
}
};

template <ex::sender Sndr, typename Log>
auto operator()(Sndr&& sndr, Log&& log) const {
return sender<std::remove_cvref_t<Sndr>, std::remove_cvref_t<Log>>{std::forward<Sndr>(sndr),
std::forward<Log>(log)};
}
};

inline constexpr logger_t logger{};
} // namespace

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

int main() {
auto log = [](std::string_view name) {
return [name](std::string_view msg) { std::cout << name << " message='" << msg << "'\n"; };
};

ex::sync_wait(logger(ex::just(), log("just()")));
ex::sync_wait(logger(ex::just() | ex::then([]() {}), log("just() | then(...)")));
ex::sync_wait(logger(ex::just() | ex::then([]() noexcept {}), log("just() | then(...)")));
ex::sync_wait(logger(ex::just(0, 1), log("just(0, 1)")));
ex::sync_wait(logger(ex::just(0, 1, 2), log("just(0, 1, 2)")));
ex::sync_wait(logger(ex::just_error(0), log("just_error(0)")) | ex::upon_error([](auto) {}));
ex::sync_wait(logger(ex::just_stopped(), log("just_stopped()")) | ex::upon_stopped([]() {}));
}
2 changes: 1 addition & 1 deletion examples/intro-1-hello-world.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ int main() {
ex::when_all(
ex::just("hello, "s),
ex::just("world"s)
) | ex::then([](auto s1, auto s2) { return s1 + s2; })
) | ex::then([](auto const& s1, auto const& s2) { return s1 + s2; })
).value_or(std::tuple(""s)
);
// clang-format on
Expand Down
2 changes: 1 addition & 1 deletion examples/intro-2-hello-async.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ int main() {
| ex::then([] { std::cout << ",\n"; return std::string(", "); }),
timer.resume_after(2s)
| ex::then([] { std::cout << "w\n"; return std::string("world"); })
) | ex::then([](auto s1, auto s2, auto s3) { return s1 + s2 + s3; })
) | ex::then([](auto const& s1, auto const& s2, auto const& s3) { return s1 + s2 + s3; })
)
).value_or(std::tuple(std::string("")));
// clang-format on
Expand Down
5 changes: 3 additions & 2 deletions examples/intro-5-consumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
#include <iostream>
#include <string>
#include <tuple>
#include <cinttypes>

namespace ex = ::beman::execution;
using namespace std::string_literals;

enum class success { one };
enum class failure { fail_one };
enum class success : std::uint8_t { one };
enum class failure : std::uint8_t { fail_one };

struct expected_to_channel_t {
template <typename Receiver>
Expand Down
129 changes: 129 additions & 0 deletions examples/meta.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// examples/meta.hpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifndef INCLUDED_EXAMPLES_META
#define INCLUDED_EXAMPLES_META

#include <beman/execution/execution.hpp>
#include <ostream>
#include <string>
#include <typeinfo>

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

namespace meta {
// The code in this namespace is a fairly basic way to print types. It can
// almost certainly be done better, in particular using reflection. However,
// that's beside the point of this example. The important part for the
// example is that meta::type<T>::name() yields a string representing the
// type T in some reasonable way
template <template <typename...> class, typename...>
struct list {
static auto name() { return "unknown-list"; }
};
template <>
struct list<::beman::execution::completion_signatures> {
static auto name() { return "ex::completion_signatures"; }
};

template <typename T>
struct type {
static auto name() { return typeid(T).name(); }
};
template <typename T>
struct type<T&> {
static auto name() { return typeid(T).name() + std::string("&"); }
};
template <typename T>
struct type<T&&> {
static auto name() { return typeid(T).name() + std::string("&&"); }
};
template <typename T>
struct type<T*> {
static auto name() { return typeid(T).name() + std::string("*"); }
};
template <typename T>
struct type<const T> {
static auto name() { return typeid(T).name() + std::string("const"); }
};
template <typename T>
struct type<volatile T> {
static auto name() { return typeid(T).name() + std::string("volatile"); }
};
template <typename T>
struct type<const volatile T> {
static auto name() { return typeid(T).name() + std::string("const volatile"); }
};
// NOLINTBEGIN(hicpp-avoid-c-arrays)
template <typename T, std::size_t N>
struct type<T[N]> {
static auto name() { return typeid(T).name() + std::string("[") + std::to_string(N) + "]"; }
};
template <typename T, std::size_t N>
struct type<T (&)[N]> {
static auto name() { return typeid(T).name() + std::string("(&)[") + std::to_string(N) + "]"; }
};
template <typename T, std::size_t N>
struct type<T (*)[N]> {
static auto name() { return typeid(T).name() + std::string("(*)[") + std::to_string(N) + "]"; }
};
// NOLINTEND(hicpp-avoid-c-arrays)

template <>
struct type<::beman::execution::set_value_t> {
static auto name() { return "ex::set_value_t"; }
};
template <>
struct type<::beman::execution::set_error_t> {
static auto name() { return "ex::set_error_t"; }
};
template <>
struct type<::beman::execution::set_stopped_t> {
static auto name() { return "ex::set_stopped_t"; }
};

template <typename T>
struct type<T()> {
static auto name() { return type<T>::name() + std::string("()"); }
};
template <typename T, typename A, typename... B>
struct type<T(A, B...)> {
static auto name() {
return type<T>::name() + std::string("(") + (type<A>::name() + ... + (std::string(", ") + type<B>::name())) +
")";
}
};
template <typename T>
struct type<T (*)()> {
static auto name() { return type<T>::name() + std::string("(*)()"); }
};
template <typename T, typename A, typename... B>
struct type<T (*)(A, B...)> {
static auto name() {
return type<T>::name() + std::string("(*)(") +
(type<A>::name() + ... + (std::string(", ") + type<B>::name())) + ")";
}
};

template <template <typename...> class L>
struct type<L<>> {
static auto name() { return list<L>::name() + std::string("<>"); }
};

template <template <typename...> class L, typename T, typename... S>
struct type<L<T, S...>> {
static auto name() {
return list<L>::name() + std::string("<") + (type<T>::name() + ... + (std::string(", ") + type<S>::name())) +
">";
}
};

template <typename T>
inline std::ostream& operator<<(std::ostream& out, const type<T>& t) {
return out << t.name();
}
} // namespace meta

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

#endif
1 change: 1 addition & 0 deletions include/beman/execution/detail/basic_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <beman/execution/detail/sender_decompose.hpp>
#include <beman/execution/detail/tag_of_t.hpp>
#include <beman/execution/detail/state_type.hpp>
#include <exception>
#include <utility>

// ----------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions include/beman/execution/detail/product_type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ constexpr auto is_product_type(const ::beman::execution::detail::product_type<T.

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

Expand Down
2 changes: 2 additions & 0 deletions include/beman/execution/detail/run_loop.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class run_loop {
run_loop* loop;
Receiver receiver;

// NOLINTBEGIN(misc-no-recursion)
template <typename R>
opstate(run_loop* l, R&& rcvr) : loop(l), receiver(::std::forward<Receiver>(rcvr)) {}
auto start() & noexcept -> void {
Expand All @@ -59,6 +60,7 @@ class run_loop {
::beman::execution::set_error(::std::move(this->receiver), ::std::current_exception());
}
}
// NOLINTEND(misc-no-recursion)
auto execute() noexcept -> void override {
if (::beman::execution::get_stop_token(::beman::execution::get_env(this->receiver)).stop_requested())
::beman::execution::set_stopped(::std::move(this->receiver));
Expand Down
2 changes: 2 additions & 0 deletions include/beman/execution/detail/set_error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@ struct set_error_t {
auto operator()(Receiver&&, Error&&) const
-> void = BEMAN_EXECUTION_DELETE("the call to receiver.set_error(error) has to be noexcept");

// NOLINTBEGIN(misc-no-recursion)
template <typename Receiver, typename Error>
auto operator()(Receiver&& receiver, Error&& error) const noexcept -> void {
::std::forward<Receiver>(receiver).set_error(::std::forward<Error>(error));
}
// NOLINTEND(misc-no-recursion)
};

/*!
Expand Down
6 changes: 5 additions & 1 deletion include/beman/execution/detail/split.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <beman/execution/detail/value_types_of_t.hpp>

#include <atomic>
#include <exception>
#include <optional>
#include <variant>
#include <tuple>
Expand Down Expand Up @@ -166,7 +167,10 @@ struct impls_for<split_impl_t> : ::beman::execution::detail::default_impls {
} else if (!(*maybe_ptr)) {
// the operation was not started yet, we are first, and we start it
assert(op_state);
::beman::execution::start(*op_state);
if (op_state)
::beman::execution::start(*op_state);
else
std::terminate();
}
}

Expand Down
2 changes: 2 additions & 0 deletions include/beman/execution/detail/start.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ struct start_t {
auto operator()(const State& state) const noexcept -> void {
state.start();
}
// NOLINTBEGIN(misc-no-recursion)
template <typename State>
auto operator()(State& state) const noexcept -> void {
state.start();
}
// NOLINTEND(misc-no-recursion)
};

inline constexpr start_t start{};
Expand Down
2 changes: 1 addition & 1 deletion tests/beman/execution/exec-bulk.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ TEST(exec_bulk) {

} catch (...) {

ASSERT(nullptr == "the bulk tests shouldn't throw");
ASSERT(nullptr == +"the bulk tests shouldn't throw");
}

return EXIT_SUCCESS;
Expand Down