QtFuture::connect: disconnect signals first
During reportFinished we may call a continuation which might end up triggering one of the signals. Change-Id: I19546fcca12be71cd536e4287eb5eddd9d236830 Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> (cherry picked from commit bb85831e4de5e2c4951a0c40003ccf36f57cbd93) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
33ae5d2145
commit
9923a90100
@ -807,34 +807,34 @@ static QFuture<ArgsType<Signal>> connect(Sender *sender, Signal signal)
|
|||||||
if constexpr (std::is_void_v<ArgsType>) {
|
if constexpr (std::is_void_v<ArgsType>) {
|
||||||
connections->first =
|
connections->first =
|
||||||
QObject::connect(sender, signal, sender, [promise, connections]() mutable {
|
QObject::connect(sender, signal, sender, [promise, connections]() mutable {
|
||||||
promise.reportFinished();
|
|
||||||
QObject::disconnect(connections->first);
|
QObject::disconnect(connections->first);
|
||||||
QObject::disconnect(connections->second);
|
QObject::disconnect(connections->second);
|
||||||
|
promise.reportFinished();
|
||||||
});
|
});
|
||||||
} else if constexpr (QtPrivate::isTupleV<ArgsType>) {
|
} else if constexpr (QtPrivate::isTupleV<ArgsType>) {
|
||||||
connections->first = QObject::connect(sender, signal, sender,
|
connections->first = QObject::connect(sender, signal, sender,
|
||||||
[promise, connections](auto... values) mutable {
|
[promise, connections](auto... values) mutable {
|
||||||
promise.reportResult(std::make_tuple(values...));
|
|
||||||
promise.reportFinished();
|
|
||||||
QObject::disconnect(connections->first);
|
QObject::disconnect(connections->first);
|
||||||
QObject::disconnect(connections->second);
|
QObject::disconnect(connections->second);
|
||||||
|
promise.reportResult(std::make_tuple(values...));
|
||||||
|
promise.reportFinished();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
connections->first = QObject::connect(sender, signal, sender,
|
connections->first = QObject::connect(sender, signal, sender,
|
||||||
[promise, connections](ArgsType value) mutable {
|
[promise, connections](ArgsType value) mutable {
|
||||||
promise.reportResult(value);
|
|
||||||
promise.reportFinished();
|
|
||||||
QObject::disconnect(connections->first);
|
QObject::disconnect(connections->first);
|
||||||
QObject::disconnect(connections->second);
|
QObject::disconnect(connections->second);
|
||||||
|
promise.reportResult(value);
|
||||||
|
promise.reportFinished();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
connections->second =
|
connections->second =
|
||||||
QObject::connect(sender, &QObject::destroyed, sender, [promise, connections]() mutable {
|
QObject::connect(sender, &QObject::destroyed, sender, [promise, connections]() mutable {
|
||||||
promise.reportCanceled();
|
|
||||||
promise.reportFinished();
|
|
||||||
QObject::disconnect(connections->first);
|
QObject::disconnect(connections->first);
|
||||||
QObject::disconnect(connections->second);
|
QObject::disconnect(connections->second);
|
||||||
|
promise.reportCanceled();
|
||||||
|
promise.reportFinished();
|
||||||
});
|
});
|
||||||
|
|
||||||
return promise.future();
|
return promise.future();
|
||||||
|
@ -3228,6 +3228,25 @@ void tst_QFuture::signalConnect()
|
|||||||
QVERIFY(future.isCanceled());
|
QVERIFY(future.isCanceled());
|
||||||
QVERIFY(!future.isValid());
|
QVERIFY(!future.isValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Signal emitted, causing Sender to be destroyed
|
||||||
|
{
|
||||||
|
SenderObject *sender = new SenderObject();
|
||||||
|
|
||||||
|
auto future = QtFuture::connect(sender, &SenderObject::intArgSignal);
|
||||||
|
future.then([sender](int) {
|
||||||
|
// Scenario: Sender no longer needed, so it's deleted
|
||||||
|
delete sender;
|
||||||
|
});
|
||||||
|
|
||||||
|
QSignalSpy spy(sender, &SenderObject::destroyed);
|
||||||
|
emit sender->intArgSignal(5);
|
||||||
|
spy.wait();
|
||||||
|
|
||||||
|
QVERIFY(future.isFinished());
|
||||||
|
QVERIFY(!future.isCanceled());
|
||||||
|
QVERIFY(future.isValid());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QFuture::waitForFinished()
|
void tst_QFuture::waitForFinished()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user