diff --git a/src/qtpromise/qpromise.h b/src/qtpromise/qpromise.h index 643e67d..ab6e28b 100644 --- a/src/qtpromise/qpromise.h +++ b/src/qtpromise/qpromise.h @@ -40,6 +40,9 @@ public: inline typename QtPromisePrivate::PromiseHandler::Promise fail(TRejected&& rejected) const; + template + inline QPromise finally(THandler handler) const; + inline QPromise wait() const; void swap(QPromiseBase& other) { qSwap(m_d, other.m_d); } @@ -63,9 +66,6 @@ public: template QPromise(F&& resolver): QPromiseBase(std::forward(resolver)) { } - template - inline QPromise finally(THandler handler) const; - public: // STATIC inline static QPromise > all(const QVector >& promises); inline static QPromise resolve(T&& value); @@ -81,9 +81,6 @@ public: template QPromise(F&& resolver): QPromiseBase(std::forward(resolver)) { } - template - inline QPromise finally(THandler handler) const; - public: // STATIC inline static QPromise all(const QVector >& promises); inline static QPromise resolve(); diff --git a/src/qtpromise/qpromise.inl b/src/qtpromise/qpromise.inl index 80bd2e2..2f99be0 100644 --- a/src/qtpromise/qpromise.inl +++ b/src/qtpromise/qpromise.inl @@ -129,6 +129,16 @@ QPromiseBase::fail(TRejected&& rejected) const return then(nullptr, std::forward(rejected)); } +template +template +inline QPromise QPromiseBase::finally(THandler handler) const +{ + QPromise p = *this; + return p.then(handler, handler).then([=]() { + return p; + }); +} + template inline QPromise QPromiseBase::wait() const { @@ -150,23 +160,6 @@ inline QPromise QPromiseBase::reject(E&& error) }); } -template -template -inline QPromise QPromise::finally(THandler handler) const -{ - return this->then([=](const T& res) { - return QPromise::resolve().then(handler).then([=](){ - return res; - }); - }, [=]() { - const auto exception = std::current_exception(); - return QPromise::resolve().then(handler).then([=](){ - std::rethrow_exception(exception); - return T(); - }); - }); -} - template inline QPromise > QPromise::all(const QVector >& promises) { @@ -206,19 +199,6 @@ inline QPromise QPromise::resolve(T&& value) }); } -template -inline QPromise QPromise::finally(THandler handler) const -{ - return this->then([=]() { - return QPromise::resolve().then(handler).then([](){}); - }, [=]() { - const auto exception = std::current_exception(); - return QPromise::resolve().then(handler).then([=](){ - std::rethrow_exception(exception); - }); - }); -} - inline QPromise QPromise::all(const QVector >& promises) { const int count = promises.size(); diff --git a/tests/auto/benchmark/tst_benchmark.cpp b/tests/auto/benchmark/tst_benchmark.cpp index 4c4e791..885d1f9 100644 --- a/tests/auto/benchmark/tst_benchmark.cpp +++ b/tests/auto/benchmark/tst_benchmark.cpp @@ -14,6 +14,7 @@ private Q_SLOTS: void valueResolve(); void valueReject(); void valueThen(); + void valueFinally(); void valueDelayed(); void errorReject(); void errorThen(); @@ -129,7 +130,7 @@ void tst_benchmark::valueThen() QCOMPARE(Data::logs().ctor, 0); QCOMPARE(Data::logs().copy, 0); - QCOMPARE(Data::logs().move, 0); // move value to the promise data + QCOMPARE(Data::logs().move, 0); QCOMPARE(Data::logs().refs, 0); QCOMPARE(error, QString("foo")); QCOMPARE(value, -1); @@ -193,6 +194,36 @@ void tst_benchmark::valueDelayed() } } +void tst_benchmark::valueFinally() +{ + { // should not copy the value on continutation if fulfilled + int value = -1; + Data::logs().reset(); + QPromise::resolve(Data(42)).finally([&]() { + value = 42; + }).wait(); + + QCOMPARE(Data::logs().ctor, 1); + QCOMPARE(Data::logs().copy, 0); + QCOMPARE(Data::logs().move, 1); // move value to the input and output promise data + QCOMPARE(Data::logs().refs, 0); + QCOMPARE(value, 42); + } + { // should not create value on continutation if rejected + int value = -1; + Data::logs().reset(); + QPromise::reject(QString("foo")).finally([&]() { + value = 42; + }).wait(); + + QCOMPARE(Data::logs().ctor, 0); + QCOMPARE(Data::logs().copy, 0); + QCOMPARE(Data::logs().move, 0); + QCOMPARE(Data::logs().refs, 0); + QCOMPARE(value, 42); + } +} + void tst_benchmark::errorReject() { { // should create one copy of the error when rejected by rvalue diff --git a/tests/auto/qpromise/tst_qpromise.cpp b/tests/auto/qpromise/tst_qpromise.cpp index dc72804..14874d9 100644 --- a/tests/auto/qpromise/tst_qpromise.cpp +++ b/tests/auto/qpromise/tst_qpromise.cpp @@ -30,8 +30,10 @@ private Q_SLOTS: void failBaseClass(); void failCatchAll(); - void finallyReturns(); - void finallyReturns_void(); + void finallyFulfilled(); + void finallyFulfilled_void(); + void finallyRejected(); + void finallyRejected_void(); void finallyThrows(); void finallyThrows_void(); void finallyDelayedResolved(); @@ -355,60 +357,60 @@ void tst_qpromise::failCatchAll() QCOMPARE(error, QString("bar")); } -void tst_qpromise::finallyReturns() +void tst_qpromise::finallyFulfilled() { - { // fulfilled - int value = -1; - auto p = QPromise::resolve(42).finally([&]() { - value = 8; - return 16; // ignored! - }); + int value = -1; + auto p = QPromise::resolve(42).finally([&]() { + value = 8; + return 16; // ignored! + }); - Q_STATIC_ASSERT((std::is_same >::value)); - QCOMPARE(waitForValue(p, -1), 42); - QCOMPARE(p.isFulfilled(), true); - QCOMPARE(value, 8); - } - { // rejected - int value = -1; - auto p = QPromise::reject(QString("foo")).finally([&]() { - value = 8; - return 16; // ignored! - }); - - Q_STATIC_ASSERT((std::is_same >::value)); - QCOMPARE(waitForError(p, QString()), QString("foo")); - QCOMPARE(p.isRejected(), true); - QCOMPARE(value, 8); - } + Q_STATIC_ASSERT((std::is_same >::value)); + QCOMPARE(waitForValue(p, -1), 42); + QCOMPARE(p.isFulfilled(), true); + QCOMPARE(value, 8); } -void tst_qpromise::finallyReturns_void() +void tst_qpromise::finallyFulfilled_void() { - { // fulfilled - int value = -1; - auto p = QPromise::resolve().finally([&]() { - value = 8; - return 16; // ignored! - }); + int value = -1; + auto p = QPromise::resolve().finally([&]() { + value = 8; + return 16; // ignored! + }); - Q_STATIC_ASSERT((std::is_same >::value)); - QCOMPARE(waitForValue(p, -1, 42), 42); - QCOMPARE(p.isFulfilled(), true); - QCOMPARE(value, 8); - } - { // rejected - int value = -1; - auto p = QPromise::reject(QString("foo")).finally([&]() { - value = 8; - return 16; // ignored! - }); + Q_STATIC_ASSERT((std::is_same >::value)); + QCOMPARE(waitForValue(p, -1, 42), 42); + QCOMPARE(p.isFulfilled(), true); + QCOMPARE(value, 8); +} - Q_STATIC_ASSERT((std::is_same >::value)); - QCOMPARE(waitForError(p, QString()), QString("foo")); - QCOMPARE(p.isRejected(), true); - QCOMPARE(value, 8); - } +void tst_qpromise::finallyRejected() +{ + int value = -1; + auto p = QPromise::reject(QString("foo")).finally([&]() { + value = 8; + return 16; // ignored! + }); + + Q_STATIC_ASSERT((std::is_same >::value)); + QCOMPARE(waitForError(p, QString()), QString("foo")); + QCOMPARE(p.isRejected(), true); + QCOMPARE(value, 8); +} + +void tst_qpromise::finallyRejected_void() +{ + int value = -1; + auto p = QPromise::reject(QString("foo")).finally([&]() { + value = 8; + return 16; // ignored! + }); + + Q_STATIC_ASSERT((std::is_same >::value)); + QCOMPARE(waitForError(p, QString()), QString("foo")); + QCOMPARE(p.isRejected(), true); + QCOMPARE(value, 8); } void tst_qpromise::finallyThrows()