Fix perfect forwarding of callables in QFuture's continuations
Use universal references instead of rvalue references for passing callables in the implementations of QFuture's continuations. Change-Id: I1288c78f78f84f30c6607e505e7f9807a9272071 Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io> (cherry picked from commit b002722dabef794da0e80010b115b2c6cd6dc6b8) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
a9ba5fe7aa
commit
bc46c7b8ea
@ -347,7 +347,7 @@ QFuture<typename QFuture<T>::template ResultType<Function>>
|
||||
QFuture<T>::then(QtFuture::Launch policy, Function &&function)
|
||||
{
|
||||
QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending);
|
||||
QtPrivate::Continuation<Function, ResultType<Function>, T>::create(
|
||||
QtPrivate::Continuation<std::decay_t<Function>, ResultType<Function>, T>::create(
|
||||
std::forward<Function>(function), this, promise, policy);
|
||||
return promise.future();
|
||||
}
|
||||
@ -358,7 +358,7 @@ QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(QTh
|
||||
Function &&function)
|
||||
{
|
||||
QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending);
|
||||
QtPrivate::Continuation<Function, ResultType<Function>, T>::create(
|
||||
QtPrivate::Continuation<std::decay_t<Function>, ResultType<Function>, T>::create(
|
||||
std::forward<Function>(function), this, promise, pool);
|
||||
return promise.future();
|
||||
}
|
||||
@ -370,7 +370,8 @@ template<class Function, typename>
|
||||
QFuture<T> QFuture<T>::onFailed(Function &&handler)
|
||||
{
|
||||
QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
|
||||
QtPrivate::FailureHandler<Function, T>::create(std::forward<Function>(handler), this, promise);
|
||||
QtPrivate::FailureHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
|
||||
this, promise);
|
||||
return promise.future();
|
||||
}
|
||||
|
||||
@ -381,7 +382,8 @@ template<class Function, typename>
|
||||
QFuture<T> QFuture<T>::onCanceled(Function &&handler)
|
||||
{
|
||||
QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending);
|
||||
QtPrivate::CanceledHandler<Function, T>::create(std::forward<Function>(handler), this, promise);
|
||||
QtPrivate::CanceledHandler<std::decay_t<Function>, T>::create(std::forward<Function>(handler),
|
||||
this, promise);
|
||||
return promise.future();
|
||||
}
|
||||
|
||||
|
@ -247,20 +247,23 @@ template<typename Function, typename ResultType, typename ParentResultType>
|
||||
class Continuation
|
||||
{
|
||||
public:
|
||||
Continuation(Function &&func, const QFuture<ParentResultType> &f,
|
||||
template<typename F = Function>
|
||||
Continuation(F &&func, const QFuture<ParentResultType> &f,
|
||||
const QFutureInterface<ResultType> &p)
|
||||
: promise(p), parentFuture(f), function(std::forward<Function>(func))
|
||||
: promise(p), parentFuture(f), function(std::forward<F>(func))
|
||||
{
|
||||
}
|
||||
virtual ~Continuation() = default;
|
||||
|
||||
bool execute();
|
||||
|
||||
static void create(Function &&func, QFuture<ParentResultType> *f,
|
||||
QFutureInterface<ResultType> &p, QtFuture::Launch policy);
|
||||
template<typename F = Function>
|
||||
static void create(F &&func, QFuture<ParentResultType> *f, QFutureInterface<ResultType> &p,
|
||||
QtFuture::Launch policy);
|
||||
|
||||
static void create(Function &&func, QFuture<ParentResultType> *f,
|
||||
QFutureInterface<ResultType> &p, QThreadPool *pool);
|
||||
template<typename F = Function>
|
||||
static void create(F &&func, QFuture<ParentResultType> *f, QFutureInterface<ResultType> &p,
|
||||
QThreadPool *pool);
|
||||
|
||||
private:
|
||||
void fulfillPromiseWithResult();
|
||||
@ -285,9 +288,10 @@ template<typename Function, typename ResultType, typename ParentResultType>
|
||||
class SyncContinuation final : public Continuation<Function, ResultType, ParentResultType>
|
||||
{
|
||||
public:
|
||||
SyncContinuation(Function &&func, const QFuture<ParentResultType> &f,
|
||||
template<typename F = Function>
|
||||
SyncContinuation(F &&func, const QFuture<ParentResultType> &f,
|
||||
const QFutureInterface<ResultType> &p)
|
||||
: Continuation<Function, ResultType, ParentResultType>(std::forward<Function>(func), f, p)
|
||||
: Continuation<Function, ResultType, ParentResultType>(std::forward<F>(func), f, p)
|
||||
{
|
||||
}
|
||||
|
||||
@ -302,9 +306,10 @@ class AsyncContinuation final : public QRunnable,
|
||||
public Continuation<Function, ResultType, ParentResultType>
|
||||
{
|
||||
public:
|
||||
AsyncContinuation(Function &&func, const QFuture<ParentResultType> &f,
|
||||
template<typename F = Function>
|
||||
AsyncContinuation(F &&func, const QFuture<ParentResultType> &f,
|
||||
const QFutureInterface<ResultType> &p, QThreadPool *pool = nullptr)
|
||||
: Continuation<Function, ResultType, ParentResultType>(std::forward<Function>(func), f, p),
|
||||
: Continuation<Function, ResultType, ParentResultType>(std::forward<F>(func), f, p),
|
||||
threadPool(pool)
|
||||
{
|
||||
this->promise.setRunnable(this);
|
||||
@ -334,12 +339,13 @@ template<class Function, class ResultType>
|
||||
class FailureHandler
|
||||
{
|
||||
public:
|
||||
static void create(Function &&function, QFuture<ResultType> *future,
|
||||
template<typename F = Function>
|
||||
static void create(F &&function, QFuture<ResultType> *future,
|
||||
const QFutureInterface<ResultType> &promise);
|
||||
|
||||
FailureHandler(Function &&func, const QFuture<ResultType> &f,
|
||||
const QFutureInterface<ResultType> &p)
|
||||
: promise(p), parentFuture(f), handler(std::forward<Function>(func))
|
||||
template<typename F = Function>
|
||||
FailureHandler(F &&func, const QFuture<ResultType> &f, const QFutureInterface<ResultType> &p)
|
||||
: promise(p), parentFuture(f), handler(std::forward<F>(func))
|
||||
{
|
||||
}
|
||||
|
||||
@ -438,7 +444,8 @@ bool Continuation<Function, ResultType, ParentResultType>::execute()
|
||||
}
|
||||
|
||||
template<typename Function, typename ResultType, typename ParentResultType>
|
||||
void Continuation<Function, ResultType, ParentResultType>::create(Function &&func,
|
||||
template<typename F>
|
||||
void Continuation<Function, ResultType, ParentResultType>::create(F &&func,
|
||||
QFuture<ParentResultType> *f,
|
||||
QFutureInterface<ResultType> &p,
|
||||
QtFuture::Launch policy)
|
||||
@ -461,10 +468,10 @@ void Continuation<Function, ResultType, ParentResultType>::create(Function &&fun
|
||||
Continuation<Function, ResultType, ParentResultType> *continuationJob = nullptr;
|
||||
if (launchAsync) {
|
||||
continuationJob = new AsyncContinuation<Function, ResultType, ParentResultType>(
|
||||
std::forward<Function>(func), *f, p, pool);
|
||||
std::forward<F>(func), *f, p, pool);
|
||||
} else {
|
||||
continuationJob = new SyncContinuation<Function, ResultType, ParentResultType>(
|
||||
std::forward<Function>(func), *f, p);
|
||||
std::forward<F>(func), *f, p);
|
||||
}
|
||||
|
||||
p.setLaunchAsync(launchAsync);
|
||||
@ -484,7 +491,8 @@ void Continuation<Function, ResultType, ParentResultType>::create(Function &&fun
|
||||
}
|
||||
|
||||
template<typename Function, typename ResultType, typename ParentResultType>
|
||||
void Continuation<Function, ResultType, ParentResultType>::create(Function &&func,
|
||||
template<typename F>
|
||||
void Continuation<Function, ResultType, ParentResultType>::create(F &&func,
|
||||
QFuture<ParentResultType> *f,
|
||||
QFutureInterface<ResultType> &p,
|
||||
QThreadPool *pool)
|
||||
@ -492,7 +500,7 @@ void Continuation<Function, ResultType, ParentResultType>::create(Function &&fun
|
||||
Q_ASSERT(f);
|
||||
|
||||
auto continuationJob = new AsyncContinuation<Function, ResultType, ParentResultType>(
|
||||
std::forward<Function>(func), *f, p, pool);
|
||||
std::forward<F>(func), *f, p, pool);
|
||||
p.setLaunchAsync(true);
|
||||
p.setThreadPool(pool);
|
||||
|
||||
@ -571,13 +579,14 @@ void fulfillPromise(QFutureInterface<T> &promise, Function &&handler)
|
||||
#ifndef QT_NO_EXCEPTIONS
|
||||
|
||||
template<class Function, class ResultType>
|
||||
void FailureHandler<Function, ResultType>::create(Function &&function, QFuture<ResultType> *future,
|
||||
template<class F>
|
||||
void FailureHandler<Function, ResultType>::create(F &&function, QFuture<ResultType> *future,
|
||||
const QFutureInterface<ResultType> &promise)
|
||||
{
|
||||
Q_ASSERT(future);
|
||||
|
||||
FailureHandler<Function, ResultType> *failureHandler = new FailureHandler<Function, ResultType>(
|
||||
std::forward<Function>(function), *future, promise);
|
||||
FailureHandler<Function, ResultType> *failureHandler =
|
||||
new FailureHandler<Function, ResultType>(std::forward<F>(function), *future, promise);
|
||||
|
||||
auto failureContinuation = [failureHandler]() mutable {
|
||||
failureHandler->run();
|
||||
@ -654,13 +663,14 @@ template<class Function, class ResultType>
|
||||
class CanceledHandler
|
||||
{
|
||||
public:
|
||||
static QFuture<ResultType> create(Function &&handler, QFuture<ResultType> *future,
|
||||
template<class F = Function>
|
||||
static QFuture<ResultType> create(F &&handler, QFuture<ResultType> *future,
|
||||
QFutureInterface<ResultType> promise)
|
||||
{
|
||||
Q_ASSERT(future);
|
||||
|
||||
auto canceledContinuation = [parentFuture = *future, promise,
|
||||
handler = std::move(handler)]() mutable {
|
||||
handler = std::forward<F>(handler)]() mutable {
|
||||
promise.reportStarted();
|
||||
|
||||
if (parentFuture.isCanceled()) {
|
||||
|
Loading…
Reference in New Issue
Block a user