@@ -993,7 +993,7 @@ auto package(E executor, F&& f)
993
993
try {
994
994
std::move (r).detach ([_p = std::move (promise)](auto && f) mutable noexcept {
995
995
if (auto e = f.exception ()) {
996
- std::move (_p).set_exception (std::move (e) );
996
+ std::move (_p).set_exception (e );
997
997
} else {
998
998
std::move (_p).set_value (invoke_void_to_monostate_result (
999
999
[&] { return std::forward<decltype (f)>(f).get_ready (); }));
@@ -1044,7 +1044,7 @@ namespace detail {
1044
1044
template <typename F>
1045
1045
struct assign_ready_future {
1046
1046
template <typename T>
1047
- static void assign (T& x, F f) {
1047
+ static void assign (T& x, F&& f) {
1048
1048
x = std::move (*(std::move (f).get_try ()));
1049
1049
}
1050
1050
};
@@ -1067,13 +1067,14 @@ struct when_all_shared {
1067
1067
std::exception_ptr _exception;
1068
1068
packaged_task<> _f;
1069
1069
1070
+ // require f is sink.
1070
1071
template <std::size_t index, typename FF>
1071
- void done (FF&& f) {
1072
+ auto done (FF&& f) -> std::enable_if_t<!std::is_lvalue_reference_v<FF>> {
1072
1073
auto run{false };
1073
1074
{
1074
1075
std::unique_lock<std::mutex> lock{_guard};
1075
1076
if (!_exception) {
1076
- assign_ready_future<FF>::assign (std::get<index >(_args), std::forward<FF> (f));
1077
+ assign_ready_future<FF>::assign (std::get<index >(_args), std::move (f));
1077
1078
if (--_remaining == 0 ) run = true ;
1078
1079
}
1079
1080
}
@@ -1181,7 +1182,7 @@ struct when_any_shared<S, void> {
1181
1182
}
1182
1183
};
1183
1184
1184
- inline void rethrow_if_false (bool x, std::exception_ptr& p) {
1185
+ inline void rethrow_if_false (bool x, const std::exception_ptr& p) {
1185
1186
if (!x) std::rethrow_exception (p);
1186
1187
}
1187
1188
@@ -1212,12 +1213,12 @@ auto apply_when_any_arg(F& f, P& p) {
1212
1213
template <std::size_t i, typename E, typename P, typename T>
1213
1214
void attach_when_arg_ (E&& executor, std::shared_ptr<P>& shared, T a) {
1214
1215
auto holds =
1215
- std::move (a).recover (std::forward<E>(executor), [_w = std::weak_ptr<P>(shared)](auto x) {
1216
+ std::move (a).recover (std::forward<E>(executor), [_w = std::weak_ptr<P>(shared)](auto && x) {
1216
1217
auto p = _w.lock ();
1217
1218
if (!p) return ;
1218
1219
1219
1220
if (auto ex = x.exception ()) {
1220
- p->failure (ex );
1221
+ p->failure (std::move (ex) );
1221
1222
} else {
1222
1223
p->template done <i>(std::move (x));
1223
1224
}
@@ -1243,7 +1244,7 @@ void attach_when_args(E&& executor, std::shared_ptr<P>& p, Ts... a) {
1243
1244
/* *************************************************************************************************/
1244
1245
1245
1246
template <typename E, typename F, typename ... Ts>
1246
- auto when_all (E executor, F f, future<Ts>... args) {
1247
+ auto when_all (const E& executor, F f, future<Ts>... args) {
1247
1248
using vt_t = voidless_tuple<Ts...>;
1248
1249
using opt_t = optional_placeholder_tuple<Ts...>;
1249
1250
using result_t = decltype (apply_ignore_placeholders (std::declval<F>(), std::declval<vt_t >()));
@@ -1263,7 +1264,7 @@ auto when_all(E executor, F f, future<Ts>... args) {
1263
1264
template <typename T>
1264
1265
struct make_when_any {
1265
1266
template <typename E, typename F, typename ... Ts>
1266
- static auto make (E executor, F f, future<T> arg, future<Ts>... args) {
1267
+ static auto make (const E& executor, F f, future<T> arg, future<Ts>... args) {
1267
1268
using result_t = detail::result_t <F, T, size_t >;
1268
1269
1269
1270
auto shared = std::make_shared<detail::when_any_shared<sizeof ...(Ts) + 1 , T>>();
@@ -1283,7 +1284,7 @@ struct make_when_any {
1283
1284
template <>
1284
1285
struct make_when_any <void > {
1285
1286
template <typename E, typename F, typename ... Ts>
1286
- static auto make (E executor, F&& f, future<Ts>... args) {
1287
+ static auto make (E&& executor, F&& f, future<Ts>... args) {
1287
1288
using result_t = detail::result_t <F, size_t >;
1288
1289
1289
1290
auto shared = std::make_shared<detail::when_any_shared<sizeof ...(Ts), void >>();
@@ -1292,7 +1293,7 @@ struct make_when_any<void> {
1292
1293
});
1293
1294
shared->_f = std::move (p.first );
1294
1295
1295
- detail::attach_when_args (executor, shared, std::move (args)...);
1296
+ detail::attach_when_args (std::forward<E>( executor) , shared, std::move (args)...);
1296
1297
1297
1298
return std::move (p.second );
1298
1299
}
@@ -1301,8 +1302,8 @@ struct make_when_any<void> {
1301
1302
/* *************************************************************************************************/
1302
1303
1303
1304
template <typename E, typename F, typename T, typename ... Ts>
1304
- auto when_any (E executor, F&& f, future<T> arg, future<Ts>... args) {
1305
- return make_when_any<T>::make (std::move (executor), std::forward<F>(f), std::move (arg),
1305
+ auto when_any (E&& executor, F&& f, future<T>&& arg, future<Ts>&& ... args) {
1306
+ return make_when_any<T>::make (std::forward<E> (executor), std::forward<F>(f), std::move (arg),
1306
1307
std::move (args)...);
1307
1308
}
1308
1309
@@ -1497,13 +1498,13 @@ struct common_context : CR {
1497
1498
/* *************************************************************************************************/
1498
1499
1499
1500
template <typename C, typename E, typename T>
1500
- void attach_tasks (size_t index, E executor, const std::shared_ptr<C>& context, T&& a) {
1501
+ void attach_tasks (size_t index, E&& executor, const std::shared_ptr<C>& context, T&& a) {
1501
1502
auto && hold = std::forward<T>(a).recover (
1502
- std::move (executor), [_context = make_weak_ptr (context), _i = index ](auto x) {
1503
+ std::forward<E> (executor), [_context = make_weak_ptr (context), _i = index ](const auto & x) {
1503
1504
auto p = _context.lock ();
1504
1505
if (!p) return ;
1505
1506
if (auto ex = x.exception ()) {
1506
- p->failure (ex , _i);
1507
+ p->failure (std::move (ex) , _i);
1507
1508
} else {
1508
1509
p->done (std::move (x), _i);
1509
1510
}
@@ -1519,7 +1520,7 @@ struct create_range_of_futures;
1519
1520
template <typename R, typename T, typename C>
1520
1521
struct create_range_of_futures <R, T, C, enable_if_copyable<T>> {
1521
1522
template <typename E, typename F, typename I>
1522
- static auto do_it (E executor, F&& f, I first, I last) {
1523
+ static auto do_it (const E& executor, F&& f, I first, I last) {
1523
1524
assert (first != last);
1524
1525
1525
1526
auto context = std::make_shared<C>(std::forward<F>(f), std::distance (first, last));
@@ -1539,7 +1540,7 @@ struct create_range_of_futures<R, T, C, enable_if_copyable<T>> {
1539
1540
template <typename R, typename T, typename C>
1540
1541
struct create_range_of_futures <R, T, C, enable_if_not_copyable<T>> {
1541
1542
template <typename E, typename F, typename I>
1542
- static auto do_it (E executor, F&& f, I first, I last) {
1543
+ static auto do_it (const E& executor, F&& f, I first, I last) {
1543
1544
assert (first != last);
1544
1545
1545
1546
auto context = std::make_shared<C>(std::forward<F>(f), std::distance (first, last));
@@ -1566,7 +1567,7 @@ template <typename E, // models task executor
1566
1567
typename F, // models functional object
1567
1568
typename I> // models ForwardIterator that reference to a range of futures of the same
1568
1569
// type
1569
- auto when_all (E executor, F f, std::pair<I, I> range) {
1570
+ auto when_all (const E& executor, F f, std::pair<I, I> range) {
1570
1571
using param_t = typename std::iterator_traits<I>::value_type::result_type;
1571
1572
using result_t = typename detail::result_of_when_all_t <F, param_t >::result_type;
1572
1573
using context_result_t =
@@ -1591,7 +1592,7 @@ template <typename E, // models task executor
1591
1592
typename F, // models functional object
1592
1593
typename I> // models ForwardIterator that reference to a range of futures of the same
1593
1594
// type
1594
- auto when_any (E executor, F&& f, std::pair<I, I> range) {
1595
+ auto when_any (const E& executor, F&& f, std::pair<I, I> range) {
1595
1596
using param_t = typename std::iterator_traits<I>::value_type::result_type;
1596
1597
using result_t = typename detail::result_of_when_any_t <F, param_t >::result_type;
1597
1598
using context_result_t = std::conditional_t <std::is_same_v<void , param_t >, void , param_t >;
@@ -1618,14 +1619,14 @@ auto when_any(E executor, F&& f, std::pair<I, I> range) {
1618
1619
#endif
1619
1620
1620
1621
template <typename E, typename F, typename ... Args>
1621
- auto async (E executor, F&& f, Args&&... args)
1622
+ auto async (const E& executor, F&& f, Args&&... args)
1622
1623
-> detail::reduced_t<detail::result_t<std::decay_t<F>, std::decay_t<Args>...>> {
1623
1624
using result_type = detail::result_t <std::decay_t <F>, std::decay_t <Args>...>;
1624
1625
1625
1626
auto [pro, fut] = package<result_type ()>(
1626
1627
executor,
1627
1628
[f = std::forward<F>(f), args = std::make_tuple (std::forward<Args>(args)...)]() mutable
1628
- -> result_type { return std::apply (std::move (f), std::move (args)); });
1629
+ -> result_type { return std::apply (std::move (f), std::move (args)); });
1629
1630
1630
1631
executor (std::move (pro));
1631
1632
0 commit comments