summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread
diff options
context:
space:
mode:
authorSona Kurazyan <sona.kurazyan@qt.io>2021-11-29 17:36:57 +0100
committerSona Kurazyan <sona.kurazyan@qt.io>2021-12-01 01:58:18 +0100
commit3be72253a6c8f469626d931b623f548cfe1e81a7 (patch)
tree40152cea64e1cf8e3e0e84d9c3ee60c2d6e98f17 /src/corelib/thread
parent1a61b85a2c04d48496a2e83359bf1d65abbc14dc (diff)
Fix QFuture continuations/handlers to work with move-only callables
std::function, which is used to store the type-erased continuation lambdas, requires the passed callable to be copy-constructible. This makes impossible to use move-only callables with continuations/handlers. In particular, it makes impossible passing lambdas that are capturing move-only objects. The workaround is to store the continuation lambda inside a wrapper for the callable, which stores the move-only lambda in a QSharedPtr and can be stored in std::function, since it's copyable. Pick-to: 6.2 Fixes: QTBUG-98493 Change-Id: I8b7a22fcf68dc132b3c533216a7a1665e9f9fb0a Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'src/corelib/thread')
-rw-r--r--src/corelib/thread/qfuture_impl.h51
1 files changed, 43 insertions, 8 deletions
diff --git a/src/corelib/thread/qfuture_impl.h b/src/corelib/thread/qfuture_impl.h
index e5a15b57ff..136892ddaf 100644
--- a/src/corelib/thread/qfuture_impl.h
+++ b/src/corelib/thread/qfuture_impl.h
@@ -498,6 +498,17 @@ bool Continuation<Function, ResultType, ParentResultType>::execute()
return true;
}
+// Workaround for keeping move-only lambdas inside std::function
+template<class Function>
+struct ContinuationWrapper
+{
+ ContinuationWrapper(Function &&f) : function(QSharedPointer<Function>::create(std::move(f))) { }
+ void operator()(const QFutureInterfaceBase &parentData) { (*function)(parentData); }
+
+private:
+ QSharedPointer<Function> function;
+};
+
template<typename Function, typename ResultType, typename ParentResultType>
template<typename F>
void Continuation<Function, ResultType, ParentResultType>::create(F &&func,
@@ -543,8 +554,10 @@ void Continuation<Function, ResultType, ParentResultType>::create(F &&func,
continuationJob = nullptr;
}
};
-
- f->d.setContinuation(std::move(continuation), p.d);
+ if constexpr (!std::is_copy_constructible_v<Function>)
+ f->d.setContinuation(ContinuationWrapper(std::move(continuation)), p.d);
+ else
+ f->d.setContinuation(std::move(continuation), p.d);
}
template<typename Function, typename ResultType, typename ParentResultType>
@@ -573,7 +586,10 @@ void Continuation<Function, ResultType, ParentResultType>::create(F &&func,
}
};
- f->d.setContinuation(std::move(continuation), p.d);
+ if constexpr (!std::is_copy_constructible_v<Function>)
+ f->d.setContinuation(ContinuationWrapper(std::move(continuation)), p.d);
+ else
+ f->d.setContinuation(std::move(continuation), p.d);
}
template<typename Function, typename ResultType, typename ParentResultType>
@@ -596,7 +612,10 @@ void Continuation<Function, ResultType, ParentResultType>::create(F &&func,
});
};
- f->d.setContinuation(std::move(continuation), p.d);
+ if constexpr (!std::is_copy_constructible_v<Function>)
+ f->d.setContinuation(ContinuationWrapper(std::move(continuation)), p.d);
+ else
+ f->d.setContinuation(std::move(continuation), p.d);
}
template<typename Function, typename ResultType, typename ParentResultType>
@@ -675,7 +694,10 @@ void FailureHandler<Function, ResultType>::create(F &&function, QFuture<ResultTy
failureHandler.run();
};
- future->d.setContinuation(std::move(failureContinuation));
+ if constexpr (!std::is_copy_constructible_v<Function>)
+ future->d.setContinuation(ContinuationWrapper(std::move(failureContinuation)));
+ else
+ future->d.setContinuation(std::move(failureContinuation));
}
template<class Function, class ResultType>
@@ -699,7 +721,10 @@ void FailureHandler<Function, ResultType>::create(F &&function, QFuture<ResultTy
});
};
- future->d.setContinuation(std::move(failureContinuation));
+ if constexpr (!std::is_copy_constructible_v<Function>)
+ future->d.setContinuation(ContinuationWrapper(std::move(failureContinuation)));
+ else
+ future->d.setContinuation(std::move(failureContinuation));
}
template<class Function, class ResultType>
@@ -782,7 +807,12 @@ public:
auto parentFuture = QFutureInterface<ResultType>(parentData).future();
run(std::forward<F>(handler), parentFuture, promise);
};
- future->d.setContinuation(std::move(canceledContinuation));
+
+ if constexpr (!std::is_copy_constructible_v<Function>)
+ future->d.setContinuation(ContinuationWrapper(std::move(canceledContinuation)));
+ else
+ future->d.setContinuation(std::move(canceledContinuation));
+
return promise.future();
}
@@ -802,7 +832,12 @@ public:
run(std::forward<F>(handler), parentFuture, promise);
});
};
- future->d.setContinuation(std::move(canceledContinuation));
+
+ if constexpr (!std::is_copy_constructible_v<Function>)
+ future->d.setContinuation(ContinuationWrapper(std::move(canceledContinuation)));
+ else
+ future->d.setContinuation(std::move(canceledContinuation));
+
return promise.future();
}