summaryrefslogtreecommitdiffstats
path: root/tests
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 /tests
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 'tests')
-rw-r--r--tests/auto/corelib/thread/qfuture/CMakeLists.txt5
-rw-r--r--tests/auto/corelib/thread/qfuture/tst_qfuture.cpp66
2 files changed, 71 insertions, 0 deletions
diff --git a/tests/auto/corelib/thread/qfuture/CMakeLists.txt b/tests/auto/corelib/thread/qfuture/CMakeLists.txt
index dcf7846fd2..df5826032d 100644
--- a/tests/auto/corelib/thread/qfuture/CMakeLists.txt
+++ b/tests/auto/corelib/thread/qfuture/CMakeLists.txt
@@ -12,3 +12,8 @@ qt_internal_add_test(tst_qfuture
PUBLIC_LIBRARIES
Qt::CorePrivate
)
+
+qt_internal_extend_target(tst_qmetatype CONDITION MSVC
+ COMPILE_OPTIONS
+ /bigobj
+)
diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
index 385fbe7fca..f97caa0633 100644
--- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
+++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
@@ -145,6 +145,7 @@ private slots:
void onCanceled();
void cancelContinuations();
void continuationsWithContext();
+ void continuationsWithMoveOnlyLambda();
#if 0
// TODO: enable when QFuture::takeResults() is enabled
void takeResults();
@@ -3111,6 +3112,71 @@ void tst_QFuture::continuationsWithContext()
thread.wait();
}
+void tst_QFuture::continuationsWithMoveOnlyLambda()
+{
+ // .then()
+ {
+ std::unique_ptr<int> uniquePtr(new int(42));
+ auto future = QtFuture::makeReadyFuture().then([p = std::move(uniquePtr)] { return *p; });
+ QCOMPARE(future.result(), 42);
+ }
+ // .then() with thread pool
+ {
+ QThreadPool pool;
+
+ std::unique_ptr<int> uniquePtr(new int(42));
+ auto future =
+ QtFuture::makeReadyFuture().then(&pool, [p = std::move(uniquePtr)] { return *p; });
+ QCOMPARE(future.result(), 42);
+ }
+ // .then() with context
+ {
+ QObject object;
+
+ std::unique_ptr<int> uniquePtr(new int(42));
+ auto future = QtFuture::makeReadyFuture().then(&object,
+ [p = std::move(uniquePtr)] { return *p; });
+ QCOMPARE(future.result(), 42);
+ }
+
+ // .onCanceled()
+ {
+ std::unique_ptr<int> uniquePtr(new int(42));
+ auto future =
+ createCanceledFuture<int>().onCanceled([p = std::move(uniquePtr)] { return *p; });
+ QCOMPARE(future.result(), 42);
+ }
+
+ // .onCanceled() with context
+ {
+ QObject object;
+
+ std::unique_ptr<int> uniquePtr(new int(42));
+ auto future = createCanceledFuture<int>().onCanceled(
+ &object, [p = std::move(uniquePtr)] { return *p; });
+ QCOMPARE(future.result(), 42);
+ }
+
+#ifndef QT_NO_EXCEPTIONS
+ // .onFailed()
+ {
+ std::unique_ptr<int> uniquePtr(new int(42));
+ auto future = QtFuture::makeExceptionalFuture<int>(QException())
+ .onFailed([p = std::move(uniquePtr)] { return *p; });
+ QCOMPARE(future.result(), 42);
+ }
+ // .onFailed() with context
+ {
+ QObject object;
+
+ std::unique_ptr<int> uniquePtr(new int(42));
+ auto future = QtFuture::makeExceptionalFuture<int>(QException())
+ .onFailed(&object, [p = std::move(uniquePtr)] { return *p; });
+ QCOMPARE(future.result(), 42);
+ }
+#endif // QT_NO_EXCEPTIONS
+}
+
void tst_QFuture::testSingleResult(const UniquePtr &p)
{
QVERIFY(p.get() != nullptr);