diff options
author | Sona Kurazyan <sona.kurazyan@qt.io> | 2021-11-29 17:36:57 +0100 |
---|---|---|
committer | Sona Kurazyan <sona.kurazyan@qt.io> | 2021-12-01 01:58:18 +0100 |
commit | 3be72253a6c8f469626d931b623f548cfe1e81a7 (patch) | |
tree | 40152cea64e1cf8e3e0e84d9c3ee60c2d6e98f17 /tests/auto | |
parent | 1a61b85a2c04d48496a2e83359bf1d65abbc14dc (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/auto')
-rw-r--r-- | tests/auto/corelib/thread/qfuture/CMakeLists.txt | 5 | ||||
-rw-r--r-- | tests/auto/corelib/thread/qfuture/tst_qfuture.cpp | 66 |
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); |