Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
4 changes: 3 additions & 1 deletion include/exec/libdispatch_queue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,8 @@ namespace experimental::execution
_WITH_PRETTY_SENDER_<__copy_cvref_t<Self, Sender>>,
_WITH_ENVIRONMENT_(Env...)>();
}
else if constexpr (__nothrow_applicable<Fun &, arg_pack_t>)
else if constexpr (__nothrow_applicable<Fun &, arg_pack_t>
&& __nothrow_decay_copyable<Args...>)
{
return completion_signatures<value_sig_t>();
}
Expand Down Expand Up @@ -481,6 +482,7 @@ namespace experimental::execution
STDEXEC_CATCH_ALL
{
STDEXEC::set_error(std::move(shared_state_.rcvr_), std::current_exception());
return;
}
}
else
Expand Down
47 changes: 47 additions & 0 deletions test/exec/test_libdispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "exec/libdispatch_queue.hpp"
#include "stdexec/execution.hpp"
#include "test_common/catch2.hpp"
#include "test_common/type_helpers.hpp"

#include <numeric>
#include <utility>
Expand Down Expand Up @@ -106,5 +107,51 @@ namespace
FAIL("invalid exception caught");
}
}

TEST_CASE("libdispatch bulk stops after value capture fails")
{
struct value_capture_error
{};

struct throwing_value
{
throwing_value() = default;

throwing_value(throwing_value const &)
{
throw value_capture_error{};
}

throwing_value(throwing_value &&)
{
throw value_capture_error{};
}
};

exec::libdispatch_queue queue;
auto sch = queue.get_scheduler();

auto sender = STDEXEC::schedule(sch) | STDEXEC::then([]() noexcept { return throwing_value{}; })
| STDEXEC::bulk(STDEXEC::par, 0, [](int, throwing_value &) noexcept {});

STATIC_REQUIRE(
set_equivalent<STDEXEC::completion_signatures_of_t<decltype(sender), STDEXEC::env<>>,
STDEXEC::completion_signatures<STDEXEC::set_value_t(throwing_value),
STDEXEC::set_error_t(std::exception_ptr),
STDEXEC::set_stopped_t()>>);

STDEXEC_TRY
{
STDEXEC::sync_wait(std::move(sender));
CHECK(false);
}
STDEXEC_CATCH(value_capture_error const &)
{
}
STDEXEC_CATCH_ALL
{
FAIL("invalid exception caught");
}
}
#endif
} // namespace
Loading