Skip to content

Commit f71dc7d

Browse files
authored
Merge pull request #2441 from darkdi/darkdi/libdispatch-lvalue-callbacks
Probe libdispatch bulk callbacks as lvalues
2 parents c90645a + 3a7eb73 commit f71dc7d

2 files changed

Lines changed: 63 additions & 6 deletions

File tree

‎include/exec/libdispatch_queue.hpp‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,10 @@ namespace experimental::execution
6262
struct bulk_shared_state;
6363

6464
template <class Fun, class Shape, class... Args>
65-
requires STDEXEC::__callable<Fun, Shape, Shape, STDEXEC::__decay_t<Args> &...>
66-
using bulk_non_throwing_t =
67-
STDEXEC::__mbool<STDEXEC::__nothrow_callable<Fun, Shape, Shape, STDEXEC::__decay_t<Args> &...>
68-
&& STDEXEC::__nothrow_decay_copyable<Args...>>;
65+
requires STDEXEC::__callable<Fun &, Shape, Shape, STDEXEC::__decay_t<Args> &...>
66+
using bulk_non_throwing_t = STDEXEC::__mbool<
67+
STDEXEC::__nothrow_callable<Fun &, Shape, Shape, STDEXEC::__decay_t<Args> &...>
68+
&& STDEXEC::__nothrow_decay_copyable<Args...>>;
6969

7070
template <class CvSender, class Receiver, class Shape, class Fun, bool MayThrow>
7171
struct bulk_receiver;

‎test/exec/test_libdispatch.cpp‎

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414
* limitations under the License.
1515
*/
1616

17-
#include "exec/libdispatch_queue.hpp"
18-
#include "stdexec/execution.hpp"
1917
#include "test_common/catch2.hpp"
18+
19+
#include "stdexec/execution.hpp"
20+
21+
#include "exec/libdispatch_queue.hpp"
2022
#include "test_common/type_helpers.hpp"
2123

2224
#include <atomic>
@@ -196,7 +198,62 @@ namespace
196198
CHECK(indices == std::vector<int>{0, 1, 2, 3});
197199
}
198200

201+
TEST_CASE("libdispatch bulk accepts lvalue-only callbacks")
202+
{
203+
struct callback
204+
{
205+
std::atomic<int> *calls;
206+
207+
void operator()(int begin, int end) & noexcept
208+
{
209+
calls->fetch_add(end - begin);
210+
}
211+
212+
void operator()(int, int) && = delete;
213+
};
214+
215+
exec::libdispatch_queue queue;
216+
auto check = [&](auto policy)
217+
{
218+
for (int shape: {0, 8})
219+
{
220+
std::atomic<int> calls{0};
221+
auto sender = STDEXEC::schedule(queue.get_scheduler())
222+
| STDEXEC::bulk_chunked(policy, shape, callback{&calls});
223+
REQUIRE(STDEXEC::sync_wait(std::move(sender)).has_value());
224+
CHECK(calls.load() == shape);
225+
}
226+
};
227+
228+
check(STDEXEC::par);
229+
check(STDEXEC::seq);
230+
}
231+
199232
#if !STDEXEC_NO_STDCPP_EXCEPTIONS()
233+
TEST_CASE("libdispatch bulk catches exceptions from lvalue-qualified callbacks")
234+
{
235+
struct callback
236+
{
237+
void operator()(int, int) &
238+
{
239+
throw 42;
240+
}
241+
242+
void operator()(int, int) && noexcept {}
243+
};
244+
245+
exec::libdispatch_queue queue;
246+
auto check = [&](auto policy)
247+
{
248+
auto sender = STDEXEC::schedule(queue.get_scheduler())
249+
| STDEXEC::bulk_chunked(policy, 8, callback{});
250+
CHECK_THROWS_AS(STDEXEC::sync_wait(std::move(sender)), int);
251+
};
252+
253+
check(STDEXEC::par);
254+
check(STDEXEC::seq);
255+
}
256+
200257
TEST_CASE("libdispatch bulk should handle exceptions gracefully")
201258
{
202259
exec::libdispatch_queue queue;

0 commit comments

Comments
 (0)