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:
Sona Kurazyan 2020-11-29 20:46:02 +01:00 committed by Qt Cherry-pick Bot
parent a9ba5fe7aa
commit bc46c7b8ea
2 changed files with 40 additions and 28 deletions

View File

@ -347,7 +347,7 @@ QFuture<typename QFuture<T>::template ResultType<Function>>
QFuture<T>::then(QtFuture::Launch policy, Function &&function) QFuture<T>::then(QtFuture::Launch policy, Function &&function)
{ {
QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending); 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); std::forward<Function>(function), this, promise, policy);
return promise.future(); return promise.future();
} }
@ -358,7 +358,7 @@ QFuture<typename QFuture<T>::template ResultType<Function>> QFuture<T>::then(QTh
Function &&function) Function &&function)
{ {
QFutureInterface<ResultType<Function>> promise(QFutureInterfaceBase::State::Pending); 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); std::forward<Function>(function), this, promise, pool);
return promise.future(); return promise.future();
} }
@ -370,7 +370,8 @@ template<class Function, typename>
QFuture<T> QFuture<T>::onFailed(Function &&handler) QFuture<T> QFuture<T>::onFailed(Function &&handler)
{ {
QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending); 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(); return promise.future();
} }
@ -381,7 +382,8 @@ template<class Function, typename>
QFuture<T> QFuture<T>::onCanceled(Function &&handler) QFuture<T> QFuture<T>::onCanceled(Function &&handler)
{ {
QFutureInterface<T> promise(QFutureInterfaceBase::State::Pending); 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(); return promise.future();
} }

View File

@ -247,20 +247,23 @@ template<typename Function, typename ResultType, typename ParentResultType>
class Continuation class Continuation
{ {
public: public:
Continuation(Function &&func, const QFuture<ParentResultType> &f, template<typename F = Function>
Continuation(F &&func, const QFuture<ParentResultType> &f,
const QFutureInterface<ResultType> &p) 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; virtual ~Continuation() = default;
bool execute(); bool execute();
static void create(Function &&func, QFuture<ParentResultType> *f, template<typename F = Function>
QFutureInterface<ResultType> &p, QtFuture::Launch policy); static void create(F &&func, QFuture<ParentResultType> *f, QFutureInterface<ResultType> &p,
QtFuture::Launch policy);
static void create(Function &&func, QFuture<ParentResultType> *f, template<typename F = Function>
QFutureInterface<ResultType> &p, QThreadPool *pool); static void create(F &&func, QFuture<ParentResultType> *f, QFutureInterface<ResultType> &p,
QThreadPool *pool);
private: private:
void fulfillPromiseWithResult(); void fulfillPromiseWithResult();
@ -285,9 +288,10 @@ template<typename Function, typename ResultType, typename ParentResultType>
class SyncContinuation final : public Continuation<Function, ResultType, ParentResultType> class SyncContinuation final : public Continuation<Function, ResultType, ParentResultType>
{ {
public: public:
SyncContinuation(Function &&func, const QFuture<ParentResultType> &f, template<typename F = Function>
SyncContinuation(F &&func, const QFuture<ParentResultType> &f,
const QFutureInterface<ResultType> &p) 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 Continuation<Function, ResultType, ParentResultType>
{ {
public: 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) 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) threadPool(pool)
{ {
this->promise.setRunnable(this); this->promise.setRunnable(this);
@ -334,12 +339,13 @@ template<class Function, class ResultType>
class FailureHandler class FailureHandler
{ {
public: 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); const QFutureInterface<ResultType> &promise);
FailureHandler(Function &&func, const QFuture<ResultType> &f, template<typename F = Function>
const QFutureInterface<ResultType> &p) FailureHandler(F &&func, const QFuture<ResultType> &f, const QFutureInterface<ResultType> &p)
: promise(p), parentFuture(f), handler(std::forward<Function>(func)) : 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> 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, QFuture<ParentResultType> *f,
QFutureInterface<ResultType> &p, QFutureInterface<ResultType> &p,
QtFuture::Launch policy) QtFuture::Launch policy)
@ -461,10 +468,10 @@ void Continuation<Function, ResultType, ParentResultType>::create(Function &&fun
Continuation<Function, ResultType, ParentResultType> *continuationJob = nullptr; Continuation<Function, ResultType, ParentResultType> *continuationJob = nullptr;
if (launchAsync) { if (launchAsync) {
continuationJob = new AsyncContinuation<Function, ResultType, ParentResultType>( continuationJob = new AsyncContinuation<Function, ResultType, ParentResultType>(
std::forward<Function>(func), *f, p, pool); std::forward<F>(func), *f, p, pool);
} else { } else {
continuationJob = new SyncContinuation<Function, ResultType, ParentResultType>( continuationJob = new SyncContinuation<Function, ResultType, ParentResultType>(
std::forward<Function>(func), *f, p); std::forward<F>(func), *f, p);
} }
p.setLaunchAsync(launchAsync); p.setLaunchAsync(launchAsync);
@ -484,7 +491,8 @@ void Continuation<Function, ResultType, ParentResultType>::create(Function &&fun
} }
template<typename Function, typename ResultType, typename ParentResultType> 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, QFuture<ParentResultType> *f,
QFutureInterface<ResultType> &p, QFutureInterface<ResultType> &p,
QThreadPool *pool) QThreadPool *pool)
@ -492,7 +500,7 @@ void Continuation<Function, ResultType, ParentResultType>::create(Function &&fun
Q_ASSERT(f); Q_ASSERT(f);
auto continuationJob = new AsyncContinuation<Function, ResultType, ParentResultType>( 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.setLaunchAsync(true);
p.setThreadPool(pool); p.setThreadPool(pool);
@ -571,13 +579,14 @@ void fulfillPromise(QFutureInterface<T> &promise, Function &&handler)
#ifndef QT_NO_EXCEPTIONS #ifndef QT_NO_EXCEPTIONS
template<class Function, class ResultType> 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) const QFutureInterface<ResultType> &promise)
{ {
Q_ASSERT(future); Q_ASSERT(future);
FailureHandler<Function, ResultType> *failureHandler = new FailureHandler<Function, ResultType>( FailureHandler<Function, ResultType> *failureHandler =
std::forward<Function>(function), *future, promise); new FailureHandler<Function, ResultType>(std::forward<F>(function), *future, promise);
auto failureContinuation = [failureHandler]() mutable { auto failureContinuation = [failureHandler]() mutable {
failureHandler->run(); failureHandler->run();
@ -654,13 +663,14 @@ template<class Function, class ResultType>
class CanceledHandler class CanceledHandler
{ {
public: 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) QFutureInterface<ResultType> promise)
{ {
Q_ASSERT(future); Q_ASSERT(future);
auto canceledContinuation = [parentFuture = *future, promise, auto canceledContinuation = [parentFuture = *future, promise,
handler = std::move(handler)]() mutable { handler = std::forward<F>(handler)]() mutable {
promise.reportStarted(); promise.reportStarted();
if (parentFuture.isCanceled()) { if (parentFuture.isCanceled()) {