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
22 changes: 14 additions & 8 deletions include/beman/execution26/detail/allocator_aware_move.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <beman/execution26/detail/product_type.hpp>
#include <beman/execution26/detail/get_allocator.hpp>
#include <beman/execution26/detail/get_env.hpp>
#include <exception>
#include <memory>
#include <utility>

Expand All @@ -20,16 +21,21 @@ template <typename T, typename Context>
* \internal
*/
auto allocator_aware_move(T&& obj, Context&& context) noexcept -> decltype(auto) {
if constexpr (requires { ::beman::execution26::get_allocator(::beman::execution26::get_env(context)); }) {
if constexpr (decltype(::beman::execution26::detail::is_product_type(obj))()) {
return obj.make_from(::beman::execution26::get_allocator(::beman::execution26::get_env(context)),
::std::forward<T>(obj));
try {
if constexpr (requires { ::beman::execution26::get_allocator(::beman::execution26::get_env(context)); }) {
if constexpr (decltype(::beman::execution26::detail::is_product_type(obj))()) {
return obj.make_from(::beman::execution26::get_allocator(::beman::execution26::get_env(context)),
::std::forward<T>(obj));
} else {
return ::std::make_obj_using_allocator<T>(
::beman::execution26::get_allocator(::beman::execution26::get_env(context)),
::std::forward<T>(obj));
}
} else {
return ::std::make_obj_using_allocator<T>(
::beman::execution26::get_allocator(::beman::execution26::get_env(context)), ::std::forward<T>(obj));
return ::std::forward<T>(obj);
}
} else {
return ::std::forward<T>(obj);
} catch (...) {
::std::terminate(); //-dk:TODO investigate if that can be avoided
}
}
} // namespace beman::execution26::detail
Expand Down
14 changes: 6 additions & 8 deletions include/beman/execution26/detail/product_type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,17 @@ struct product_type_base<::std::index_sequence<I...>, T...>
}
template <::std::size_t J>
auto get() const& -> decltype(auto) {
return this->element_get<J>(::std::move(*this));
return this->element_get<J>(*this);
}

template <::std::size_t J, typename Allocator, typename Self>
static auto make_element(Allocator&& alloc, Self&& self) -> decltype(auto) {
using type = ::std::remove_cvref_t<decltype(std::forward<Self>(self).template element_get<J>(
std::forward<Self>(self)))>;
using type = ::std::remove_cvref_t<decltype(product_type_base::element_get<J>(std::forward<Self>(self)))>;
if constexpr (::std::uses_allocator_v<type, Allocator>)
return ::std::make_obj_using_allocator<type>(
alloc, std::forward<Self>(self).template element_get<J>(std::forward<Self>(self)));
return ::std::make_obj_using_allocator<type>(alloc,
product_type_base::element_get<J>(std::forward<Self>(self)));
else
return std::forward<Self>(self).template element_get<J>(std::forward<Self>(self));
return product_type_base::element_get<J>(std::forward<Self>(self));
}

auto operator==(const product_type_base&) const -> bool = default;
Expand All @@ -69,8 +68,7 @@ template <typename... T>
struct product_type : ::beman::execution26::detail::product_type_base<::std::index_sequence_for<T...>, T...> {
template <typename Allocator, typename Product, std::size_t... I>
static auto make_from(Allocator&& allocator, Product&& product, std::index_sequence<I...>) -> product_type {
return {
::std::forward<Product>(product).template make_element<I>(allocator, ::std::forward<Product>(product))...};
return {product_type::template make_element<I>(allocator, ::std::forward<Product>(product))...};
}

template <typename Allocator, typename Product>
Expand Down
29 changes: 17 additions & 12 deletions include/beman/execution26/detail/schedule_from.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,8 @@ using as_tuple_t = typename as_tuple<T>::type;
struct schedule_from_t {
template <::beman::execution26::scheduler Scheduler, ::beman::execution26::sender Sender>
auto operator()(Scheduler&& scheduler, Sender&& sender) const {
auto domain{::beman::execution26::detail::query_with_default(::beman::execution26::get_domain,
::std::forward<Scheduler>(scheduler),
::beman::execution26::default_domain{})};
auto domain{::beman::execution26::detail::query_with_default(
::beman::execution26::get_domain, scheduler, ::beman::execution26::default_domain{})};
return ::beman::execution26::transform_sender(
domain,
::beman::execution26::detail::make_sender(
Expand All @@ -78,15 +77,21 @@ struct impls_for<::beman::execution26::detail::schedule_from_t> : ::beman::execu
State* state;

auto set_value() && noexcept -> void {
::std::visit(
[this]<typename Tuple>(Tuple& result) noexcept -> void {
if constexpr (not::std::same_as<::std::monostate, Tuple>) {
::std::apply([this](auto&& tag,
auto&&... args) { tag(std::move(state->receiver), std::move(args)...); },
result);
}
},
state->async_result);
try {
::std::visit(
[this]<typename Tuple>(Tuple& result) noexcept -> void {
if constexpr (not::std::same_as<::std::monostate, Tuple>) {
::std::apply(
[this](auto&& tag, auto&&... args) {
tag(::std::move(this->state->receiver), ::std::move(args)...);
},
result);
}
},
state->async_result);
} catch (...) {
::beman::execution26::set_error(::std::move(state->receiver), ::std::current_exception());
}
}

template <typename Error>
Expand Down
18 changes: 11 additions & 7 deletions include/beman/execution26/detail/when_all.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,17 @@ struct impls_for<::beman::execution26::detail::when_all_t> : ::beman::execution2
} break;
case disposition::error:
this->on_stop.reset();
::std::visit(
[&]<typename Error>(Error& error) noexcept {
if constexpr (!::std::same_as<Error, nonesuch>) {
::beman::execution26::set_error(::std::move(receiver), ::std::move(error));
}
},
this->errors);
try {
::std::visit(
[&]<typename Error>(Error& error) noexcept {
if constexpr (!::std::same_as<Error, nonesuch>) {
::beman::execution26::set_error(::std::move(receiver), ::std::move(error));
}
},
this->errors);
} catch (...) {
::beman::execution26::set_error(::std::move(receiver), ::std::current_exception());
}
break;
case disposition::stopped:
this->on_stop.reset();
Expand Down
2 changes: 2 additions & 0 deletions include/beman/execution26/detail/with_await_transform.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// ----------------------------------------------------------------------------

namespace beman::execution26::detail {
// NOLINTBEGIN(bugprone-crtp-constructor-accessibility)
template <typename Derived>
struct with_await_transform {
template <typename T>
Expand All @@ -24,6 +25,7 @@ struct with_await_transform {
return ::std::forward<T>(obj).as_awaitable(static_cast<Derived&>(*this));
}
};
// NOLINTEND(bugprone-crtp-constructor-accessibility)
} // namespace beman::execution26::detail

// ----------------------------------------------------------------------------
Expand Down
2 changes: 2 additions & 0 deletions tests/beman/execution26/exec-fwd-env.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ TEST(exec_fwd_env) {
static_assert(test_std::forwarding_query(dynamic_query()));
static_assert(test_std::forwarding_query(dynamic_query{true}));
static_assert(not test_std::forwarding_query(dynamic_query{false}));
// NOLINTNEXTLINE(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
ASSERT(test_std::forwarding_query(dynamic_query{true}));
// NOLINTNEXTLINE(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
ASSERT(not test_std::forwarding_query(dynamic_query{false}));
}
9 changes: 9 additions & 0 deletions tests/beman/execution26/exec-general.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,17 @@ struct error {

struct non_movable {
non_movable(non_movable&&) = delete;
non_movable(const non_movable&) = delete;
~non_movable() = default;
auto operator=(non_movable&&) -> non_movable& = delete;
auto operator=(const non_movable&) -> non_movable& = delete;
};
struct non_copyable {
non_copyable(non_copyable&&) = default;
non_copyable(const non_copyable&) = delete;
~non_copyable() = default;
auto operator=(non_copyable&&) -> non_copyable& = default;
auto operator=(const non_copyable&) -> non_copyable& = delete;
};

auto test_movable_value() -> void {
Expand Down Expand Up @@ -63,6 +70,7 @@ auto test_as_except_ptr() -> void {
} catch (error& e) {
ASSERT(e.value == 17);
} catch (...) {
// NOLINTNEXTLINE(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
ASSERT(nullptr == "wrong exception type produced by as_except_ptr for random error");
}

Expand All @@ -73,6 +81,7 @@ auto test_as_except_ptr() -> void {
} catch (std::system_error& e) {
ASSERT(e.code() == errc);
} catch (...) {
// NOLINTNEXTLINE(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
ASSERT(nullptr == "wrong exception type produced by as_except_ptr for error code");
}
}
Expand Down
8 changes: 6 additions & 2 deletions tests/beman/execution26/exec-get-env.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@
namespace {
struct with_non_env;
struct non_env {
non_env(non_env&&) = delete;
non_env(const non_env&) = delete;
auto operator=(non_env&&) -> non_env& = delete;
auto operator=(const non_env&) -> non_env& = delete;

private:
friend struct with_non_env;
non_env() = default;
non_env(non_env&&) = delete;
non_env() = default;
~non_env() = default;
};
struct with_non_env {
Expand Down
10 changes: 7 additions & 3 deletions tests/beman/execution26/exec-just.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
namespace {
struct not_movable {
not_movable() = default;
not_movable(const not_movable&) = delete;
not_movable(not_movable&&) = delete;
~not_movable() = default;
auto operator=(const not_movable&) -> not_movable& = delete;
auto operator=(not_movable&&) -> not_movable& = delete;
};
template <bool Expect, typename Completion, typename CPO, typename... T>
auto test_just_constraints(CPO const& cpo, T&&... args) -> void {
Expand Down Expand Up @@ -60,7 +64,7 @@ auto test_just_constraints() -> void {
template <typename... T>
struct value_receiver {
using receiver_concept = test_std::receiver_t;
bool* called;
bool* called{};
test_detail::product_type<std::decay_t<T>...> expect{};

template <typename... A>
Expand Down Expand Up @@ -206,7 +210,7 @@ TEST(exec_just) {
test_just();
test_just_allocator();
} catch (...) {
ASSERT(nullptr ==
"the just tests shouldn't throw"); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
// NOLINTNEXTLINE(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
ASSERT(nullptr == "the just tests shouldn't throw");
}
}
47 changes: 26 additions & 21 deletions tests/beman/execution26/exec-opstate-start.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,63 +10,68 @@

namespace {
struct receiver {
int value{};
int& value;
auto set_value(int value) && noexcept -> void { this->value = value; }
};

struct non_opstate {};
struct non_opstate {
receiver rcvr;
};

template <bool Noexcept>
struct opstate {
receiver* rcvr;
auto start() const noexcept(Noexcept) -> void { test_std::set_value(::std::move(*rcvr), 42); }
receiver rcvr;
auto start() const noexcept(Noexcept) -> void { test_std::set_value(receiver(this->rcvr.value), 42); }
};

template <typename State>
auto test_start_argument_type() {
receiver rcvr{};
State state{&rcvr};
receiver crcvr{};
const State cstate{&crcvr};
int value{};
State state{receiver{value}};
int cvalue{};
const State cstate{receiver{cvalue}};

static_assert(requires { test_std::start(state); });
static_assert(requires { test_std::start(cstate); });

static_assert(not requires { test_std::start(State(&rcvr)); });
static_assert(not requires { test_std::start(State(receiver{value})); });
static_assert(not requires { test_std::start(std::move(state)); });
static_assert(not requires { test_std::start(std::move(cstate)); });
}

template <typename State>
auto test_start_member() {
State state{};
int value{};
State state{receiver{value}};
static_assert(not requires { test_std::start(state); });
State cstate{};
const State cstate{receiver{value}};
static_assert(not requires { test_std::start(cstate); });
}

template <typename State>
auto test_start_noexcept() {
State state{};
int value{};
State state{receiver{value}};
static_assert(noexcept(state));
State cstate{};
int cvalue{};
const State cstate{receiver{cvalue}};
static_assert(noexcept(cstate));
}

template <typename State>
auto test_start_call() {
receiver rcvr{};
State state{&rcvr};
receiver crcvr{};
const State cstate{&crcvr};
int value{};
State state{receiver{value}};
int cvalue{};
const State cstate{receiver{cvalue}};

ASSERT(rcvr.value == 0);
ASSERT(value == 0);
test_std::start(state);
ASSERT(rcvr.value == 42);
ASSERT(value == 42);

ASSERT(crcvr.value == 0);
ASSERT(cvalue == 0);
test_std::start(cstate);
ASSERT(crcvr.value == 42);
ASSERT(cvalue == 42);
}
} // namespace

Expand Down
14 changes: 5 additions & 9 deletions tests/beman/execution26/exec-set-error.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,10 @@ struct arg {
};
struct arg_throwing {};

struct throws {
throws() = default;
throws(const throws&) {}
};

struct receiver {
template <typename Error>
auto set_error(Error&&) noexcept -> void {}
auto set_error(throws) noexcept -> void {}
auto set_error(int) noexcept -> void {}
// NOTLINTNEXTLINE(performance-unnecessary-value-param)
auto set_error(test::throws) noexcept(false) -> void {}
auto set_error(arg a) noexcept -> void { ASSERT(a.value == 43); }
auto set_error(arg_throwing) -> void {}
};
Expand All @@ -42,8 +37,9 @@ void test_callable() {

template <typename R>
auto test_noexcept() {
test::throws obj{};
static_assert(requires { test_std::set_error(std::declval<R>(), arg()); });
static_assert(not requires { test_std::set_error(std::declval<R>(), throws()); });
static_assert(not requires { test_std::set_error(std::declval<R>(), obj); });
static_assert(not requires { test_std::set_error(std::declval<R>(), arg_throwing()); });
}
} // namespace
Expand Down
Loading