QPromise: fix documentation re:setException() after cancel() or finish()
The implementation checks the state and returns without storing the exception when its canceled or finished. Add tests for both situations. Done-with: Ivan Solovev <ivan.solovev@qt.io> (analysis and phrasing) Pick-to: 6.5 6.2 Fixes: QTBUG-128405 Change-Id: I4610a022ea12e1bc9ce24cb17b972b5b9e051f0a Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> (cherry picked from commit 6efec3850da188d3bba075185aa6e5c264c815eb) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
a11b0a3d29
commit
5a9c513231
@ -162,7 +162,7 @@
|
||||
\note You can set at most one exception throughout the computation
|
||||
execution.
|
||||
|
||||
\note This method must not be used after QFuture::cancel() or
|
||||
\note This method has no effect after QFuture::cancel() or
|
||||
finish().
|
||||
|
||||
\sa isCanceled()
|
||||
|
@ -9,13 +9,22 @@
|
||||
#include <qfuture.h>
|
||||
#include <qfuturewatcher.h>
|
||||
#include <qpromise.h>
|
||||
#include <QtCore/qsemaphore.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <QtCore/q20type_traits.h>
|
||||
#include <chrono>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
template <typename T>
|
||||
struct promise_type {};
|
||||
template <typename T>
|
||||
struct promise_type<QPromise<T>> : q20::type_identity<T> {};
|
||||
template <typename T>
|
||||
using promise_type_t = typename promise_type<T>::type;
|
||||
|
||||
class tst_QPromise : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -28,6 +37,8 @@ private slots:
|
||||
void addResultOutOfOrder();
|
||||
#ifndef QT_NO_EXCEPTIONS
|
||||
void setException();
|
||||
void setExceptionAfterCancelDoesNothing(); // QTBUG-128405
|
||||
void setExceptionAfterFinishDoesNothing();
|
||||
#endif
|
||||
void cancel();
|
||||
void progress();
|
||||
@ -320,6 +331,69 @@ void tst_QPromise::setException()
|
||||
RUN_TEST_FUNC(testExceptionCaught, QPromise<MoveOnlyType>(),
|
||||
std::make_exception_ptr(TestException()));
|
||||
}
|
||||
|
||||
void tst_QPromise::setExceptionAfterCancelDoesNothing()
|
||||
{
|
||||
struct TestException {};
|
||||
|
||||
auto test = [](auto promise, auto exception) {
|
||||
auto f = promise.future();
|
||||
FutureWatcher r(f);
|
||||
QSemaphore sem;
|
||||
QSemaphoreReleaser rel(sem);
|
||||
ThreadWrapper t([&] {
|
||||
auto p = std::move(promise);
|
||||
p.start();
|
||||
sem.acquire(); // wait for cancel() in main thread
|
||||
p.setException(std::move(exception));
|
||||
});
|
||||
|
||||
f.cancel();
|
||||
rel.cancel()->release(); // give a go for setException() in worker thread
|
||||
|
||||
t.join();
|
||||
|
||||
QVERIFY(f.isCanceled());
|
||||
QVERIFY(!r.thenCalled);
|
||||
QVERIFY(!r.onFailedCalled);
|
||||
QVERIFY(r.onCanceledCalled);
|
||||
};
|
||||
|
||||
RUN_TEST_FUNC(test, QPromise<void>(), QException());
|
||||
RUN_TEST_FUNC(test, QPromise<int>(), QException());
|
||||
RUN_TEST_FUNC(test, QPromise<void>(), std::make_exception_ptr(TestException()));
|
||||
RUN_TEST_FUNC(test, QPromise<int>(), std::make_exception_ptr(TestException()));
|
||||
RUN_TEST_FUNC(test, QPromise<CopyOnlyType>(), std::make_exception_ptr(TestException()));
|
||||
RUN_TEST_FUNC(test, QPromise<MoveOnlyType>(), std::make_exception_ptr(TestException()));
|
||||
}
|
||||
|
||||
void tst_QPromise::setExceptionAfterFinishDoesNothing()
|
||||
{
|
||||
struct TestException {};
|
||||
|
||||
auto test = [](auto promise, auto exception) {
|
||||
auto f = promise.future();
|
||||
FutureWatcher r(f);
|
||||
promise.start();
|
||||
using T = promise_type_t<decltype(promise)>;
|
||||
if constexpr (!std::is_void_v<T>)
|
||||
promise.addResult(T());
|
||||
promise.finish();
|
||||
promise.setException(std::move(exception));
|
||||
|
||||
QVERIFY(f.isFinished());
|
||||
QVERIFY(r.thenCalled);
|
||||
QVERIFY(!r.onFailedCalled);
|
||||
QVERIFY(!r.onCanceledCalled);
|
||||
};
|
||||
|
||||
RUN_TEST_FUNC(test, QPromise<void>(), QException());
|
||||
RUN_TEST_FUNC(test, QPromise<int>(), QException());
|
||||
RUN_TEST_FUNC(test, QPromise<void>(), std::make_exception_ptr(TestException()));
|
||||
RUN_TEST_FUNC(test, QPromise<int>(), std::make_exception_ptr(TestException()));
|
||||
RUN_TEST_FUNC(test, QPromise<CopyOnlyType>(), std::make_exception_ptr(TestException()));
|
||||
RUN_TEST_FUNC(test, QPromise<MoveOnlyType>(), std::make_exception_ptr(TestException()));
|
||||
}
|
||||
#endif
|
||||
|
||||
void tst_QPromise::cancel()
|
||||
|
Loading…
x
Reference in New Issue
Block a user