Cleanup promise captured in resolve/reject

Make sure that QPromiseResolve and QPromiseReject release their associated promise as soon as one of them is resolved or rejected, ensuring that the promise data is cleaned up once resolved (that fixes cases where one or both of them are captured in a signal/slot connection lambda)
This commit is contained in:
Simon Brunel
2018-05-07 10:46:00 +02:00
parent 7b0cba5b9d
commit fa987a5044
4 changed files with 159 additions and 45 deletions

View File

@ -7,6 +7,9 @@
// Qt
#include <QtTest>
// STL
#include <memory>
using namespace QtPromise;
class tst_qpromise_construct : public QObject
@ -30,6 +33,8 @@ private Q_SLOTS:
void rejectSync_void();
void rejectAsync();
void rejectAsync_void();
void connectAndResolve();
void connectAndReject();
};
QTEST_MAIN(tst_qpromise_construct)
@ -228,3 +233,77 @@ void tst_qpromise_construct::rejectThrowTwoArgs_void()
QCOMPARE(waitForValue(p, -1, 42), -1);
QCOMPARE(waitForError(p, QString()), QString("foo"));
}
// https://github.com/simonbrunel/qtpromise/issues/6
void tst_qpromise_construct::connectAndResolve()
{
QScopedPointer<QObject> object(new QObject());
std::weak_ptr<int> wptr;
{
auto p = QPromise<std::shared_ptr<int>>([&](
const QPromiseResolve<std::shared_ptr<int>>& resolve,
const QPromiseReject<std::shared_ptr<int>>& reject) {
connect(object.data(), &QObject::objectNameChanged,
[=, &wptr](const QString& name) {
std::shared_ptr<int> sptr(new int(42));
wptr = sptr;
if (name == "foobar") {
resolve(sptr);
} else {
reject(42);
}
});
});
QCOMPARE(p.isPending(), true);
object->setObjectName("foobar");
QCOMPARE(waitForValue(p, std::shared_ptr<int>()), wptr.lock());
QCOMPARE(wptr.use_count(), 1l); // "p" still holds a reference
}
QCOMPARE(wptr.use_count(), 0l);
}
// https://github.com/simonbrunel/qtpromise/issues/6
void tst_qpromise_construct::connectAndReject()
{
QScopedPointer<QObject> object(new QObject());
std::weak_ptr<int> wptr;
{
auto p = QPromise<int>([&](
const QPromiseResolve<int>& resolve,
const QPromiseReject<int>& reject) {
connect(object.data(), &QObject::objectNameChanged,
[=, &wptr](const QString& name) {
std::shared_ptr<int> sptr(new int(42));
wptr = sptr;
if (name == "foobar") {
reject(sptr);
} else {
resolve(42);
}
});
});
QCOMPARE(p.isPending(), true);
object->setObjectName("foobar");
QCOMPARE(waitForError(p, std::shared_ptr<int>()), wptr.lock());
QCOMPARE(wptr.use_count(), 1l); // "p" still holds a reference
}
QCOMPARE(wptr.use_count(), 0l);
}