Do we really allow the bulk callback function to throw an exception? That is, when the bulk callback throws an exception, will that exception be propagated through the receiver's set_error(std::exception_ptr)?
Consider:
Given a scheduler sch, what should be the behavior of the following code?
try {
stdexec::sync_wait(stdexec::schedule(sch) | stdexec::bulk(std::execution::par, 1uz, [](std::size_t){
throw std::runtime_error{"xxx"};
}));
}
catch (const std::runtime_error& e) {
...
}
Can the try-catch here catch this std::runtime_error?
For the default implementation of bulk, the answer is yes, it can be caught. But for some customized bulk implementations, it may be different. For example, if sch here is a stdexec::parallel_scheduler, the program will terminate, see
|
void execute(size_t __begin, size_t __end) noexcept override |
|
{ |
|
auto __state = reinterpret_cast<_BulkState*>(this); |
|
if constexpr (_BulkState::__is_unchunked) |
|
{ |
|
(void) __end; // not used |
|
// If we are not parallelizing, we need to run all the iterations sequentially. |
|
size_t __increments = 1; |
|
if constexpr (!_BulkState::__parallelize) |
|
{ |
|
__increments = static_cast<size_t>(__state->__size_); |
|
} |
|
for (size_t __i = __begin; __i < __begin + __increments; __i++) |
|
{ |
|
std::apply([&](auto&&... __args) { __state->__fun_(__i, __args...); }, |
|
__base_t::__arguments_.__get()); |
|
} |
|
} |
|
else |
|
{ |
|
// If we are not parallelizing, we need to pass the entire range to the functor. |
|
if constexpr (!_BulkState::__parallelize) |
|
{ |
|
__begin = 0; |
|
__end = static_cast<size_t>(__state->__size_); |
|
} |
|
std::apply([&](auto&&... __args) { __state->__fun_(__begin, __end, __args...); }, |
|
__base_t::__arguments_.__get()); |
|
} |
|
} |
which does not handle the case where the call to
__state->__fun_ throws an exception. However, fixing this seems a bit tricky, or should we reconsider the exception specification of
bulk_item_receiver_proxy::execute?
Do we really allow the
bulkcallback function to throw an exception? That is, when thebulkcallback throws an exception, will that exception be propagated through the receiver'sset_error(std::exception_ptr)?Consider:
Given a scheduler
sch, what should be the behavior of the following code?Can the
try-catchhere catch thisstd::runtime_error?For the default implementation of
bulk, the answer is yes, it can be caught. But for some customizedbulkimplementations, it may be different. For example, if sch here is astdexec::parallel_scheduler, the program will terminate, seestdexec/include/stdexec/__detail/__parallel_scheduler.hpp
Lines 390 to 419 in e8c349f
which does not handle the case where the call to
__state->__fun_throws an exception. However, fixing this seems a bit tricky, or should we reconsider the exception specification ofbulk_item_receiver_proxy::execute?