QtConcurrent::run: support non default-constructible return types
The QtConcurrent::RunFunctionTask class keeps a variable to store the result of QtConcurrent::run when it becomes available, so that it can be reported afterwards. This requires the result type to be default-constructible. However there's no need in storing the result, it can be reported immediately after it becomes available. Pick-to: 6.1 6.2 Fixes: QTBUG-95214 Change-Id: I95f3dbff0ab41eaa81b104a8834b37d10a0d193a Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
This commit is contained in:
parent
c4ac9e74c7
commit
642b9fce81
@ -117,37 +117,15 @@ public:
|
||||
promise.reportException(QUnhandledException(std::current_exception()));
|
||||
}
|
||||
#endif
|
||||
|
||||
reportResult();
|
||||
|
||||
promise.reportFinished();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void runFunctor() = 0;
|
||||
virtual void reportResult() {}
|
||||
|
||||
QFutureInterface<T> promise;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class RunFunctionTask : public RunFunctionTaskBase<T>
|
||||
{
|
||||
protected:
|
||||
void reportResult() override
|
||||
{
|
||||
if constexpr (std::is_move_constructible_v<T>)
|
||||
this->promise.reportAndMoveResult(std::move(result));
|
||||
else if constexpr (std::is_copy_constructible_v<T>)
|
||||
this->promise.reportResult(result);
|
||||
}
|
||||
|
||||
T result;
|
||||
};
|
||||
|
||||
template <>
|
||||
class RunFunctionTask<void> : public RunFunctionTaskBase<void> {};
|
||||
|
||||
} //namespace QtConcurrent
|
||||
|
||||
#endif //Q_QDOC
|
||||
|
@ -138,7 +138,7 @@ template <class ...Types>
|
||||
using DecayedTuple = std::tuple<std::decay_t<Types>...>;
|
||||
|
||||
template <class Function, class ...Args>
|
||||
struct StoredFunctionCall : public RunFunctionTask<InvokeResultType<Function, Args...>>
|
||||
struct StoredFunctionCall : public RunFunctionTaskBase<InvokeResultType<Function, Args...>>
|
||||
{
|
||||
StoredFunctionCall(DecayedTuple<Function, Args...> &&_data)
|
||||
: data(std::move(_data))
|
||||
@ -152,10 +152,17 @@ protected:
|
||||
return std::invoke(function, args...);
|
||||
};
|
||||
|
||||
if constexpr (std::is_void_v<InvokeResultType<Function, Args...>>)
|
||||
if constexpr (std::is_void_v<InvokeResultType<Function, Args...>>) {
|
||||
std::apply(invoke, std::move(data));
|
||||
else
|
||||
this->result = std::apply(invoke, std::move(data));
|
||||
} else {
|
||||
auto result = std::apply(invoke, std::move(data));
|
||||
|
||||
using T = InvokeResultType<Function, Args...>;
|
||||
if constexpr (std::is_move_constructible_v<T>)
|
||||
this->promise.reportAndMoveResult(std::move(result));
|
||||
else if constexpr (std::is_copy_constructible_v<T>)
|
||||
this->promise.reportResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -64,6 +64,7 @@ private slots:
|
||||
void moveOnlyType();
|
||||
void crefFunction();
|
||||
void customPromise();
|
||||
void nonDefaultConstructibleValue();
|
||||
};
|
||||
|
||||
void light()
|
||||
@ -1564,6 +1565,17 @@ void tst_QtConcurrentRun::customPromise()
|
||||
QCOMPARE(p.future().progressMaximum(), 10);
|
||||
}
|
||||
|
||||
void tst_QtConcurrentRun::nonDefaultConstructibleValue()
|
||||
{
|
||||
struct NonDefaultConstructible
|
||||
{
|
||||
explicit NonDefaultConstructible(int v) : value(v) { }
|
||||
int value = 0;
|
||||
};
|
||||
|
||||
auto future = QtConcurrent::run([] { return NonDefaultConstructible(42); });
|
||||
QCOMPARE(future.result().value, 42);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QtConcurrentRun)
|
||||
#include "tst_qtconcurrentrun.moc"
|
||||
|
@ -229,12 +229,12 @@ void tst_QFutureWatcher::canceled()
|
||||
future.waitForFinished();
|
||||
}
|
||||
|
||||
class IntTask : public RunFunctionTask<int>
|
||||
class IntTask : public RunFunctionTaskBase<int>
|
||||
{
|
||||
public:
|
||||
void runFunctor() override
|
||||
{
|
||||
result = 10;
|
||||
promise.reportResult(10);
|
||||
}
|
||||
};
|
||||
|
||||
@ -463,7 +463,7 @@ void tst_QFutureWatcher::disconnectRunningFuture()
|
||||
}
|
||||
|
||||
const int maxProgress = 100000;
|
||||
class ProgressEmitterTask : public RunFunctionTask<void>
|
||||
class ProgressEmitterTask : public RunFunctionTaskBase<void>
|
||||
{
|
||||
public:
|
||||
void runFunctor() override
|
||||
@ -493,7 +493,7 @@ void tst_QFutureWatcher::tooMuchProgress()
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class ProgressTextTask : public RunFunctionTask<T>
|
||||
class ProgressTextTask : public RunFunctionTaskBase<T>
|
||||
{
|
||||
public:
|
||||
void runFunctor() override
|
||||
|
Loading…
x
Reference in New Issue
Block a user