Create QFutures returned by QtFuture::when* methods via QPromise

This is required to ensure that the continuation attached to a
QFuture returned by QtFuture::when* methods is cleaned in the destructor
of the associated QPromise, so that it doesn't keep any ref-counted
copies to the shared data, thus preventing it from being deleted.

Task-number: QTBUG-99534
Pick-to: 6.3
Change-Id: If4e2929b2e638d6b48c95f0aef9dc886066cedbe
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
Sona Kurazyan 2022-01-18 13:35:24 +01:00
parent 614847eae9
commit afdae3618a

View File

@ -1006,13 +1006,13 @@ struct WhenAllContext
futures[index] = std::forward<T>(future);
Q_ASSERT(count > 0);
if (--count <= 0) {
promise.reportResult(futures);
promise.reportFinished();
promise.addResult(futures);
promise.finish();
}
}
QAtomicInteger<qsizetype> count;
QFutureInterface<ResultFutures> promise;
QPromise<ResultFutures> promise;
ResultFutures futures;
};
@ -1025,13 +1025,13 @@ struct WhenAnyContext
void checkForCompletion(qsizetype, T &&result)
{
if (!ready.fetchAndStoreRelaxed(true)) {
promise.reportResult(std::forward<T>(result));
promise.reportFinished();
promise.addResult(std::forward<T>(result));
promise.finish();
}
}
QAtomicInt ready = false;
QFutureInterface<ResultType> promise;
QPromise<ResultType> promise;
};
template<qsizetype Index, typename ContextType, typename... Ts>
@ -1066,7 +1066,7 @@ QFuture<OutputSequence> whenAllImpl(InputIt first, InputIt last)
auto context = QSharedPointer<QtPrivate::WhenAllContext<OutputSequence>>::create(size);
context->futures.resize(size);
context->promise.reportStarted();
context->promise.start();
qsizetype idx = 0;
for (auto it = first; it != last; ++it, ++idx) {
@ -1085,7 +1085,7 @@ QFuture<OutputSequence> whenAllImpl(Futures &&... futures)
constexpr qsizetype size = sizeof...(Futures);
auto context = QSharedPointer<QtPrivate::WhenAllContext<OutputSequence>>::create(size);
context->futures.resize(size);
context->promise.reportStarted();
context->promise.start();
QtPrivate::addCompletionHandlers(context, std::make_tuple(std::forward<Futures>(futures)...));
@ -1106,7 +1106,7 @@ QFuture<QtFuture::WhenAnyResult<typename Future<ValueType>::type>> whenAnyImpl(I
}
auto context = QSharedPointer<QtPrivate::WhenAnyContext<ResultType>>::create();
context->promise.reportStarted();
context->promise.start();
qsizetype idx = 0;
for (auto it = first; it != last; ++it, ++idx) {
@ -1125,7 +1125,7 @@ QFuture<std::variant<std::decay_t<Futures>...>> whenAnyImpl(Futures &&... future
using ResultType = std::variant<std::decay_t<Futures>...>;
auto context = QSharedPointer<QtPrivate::WhenAnyContext<ResultType>>::create();
context->promise.reportStarted();
context->promise.start();
QtPrivate::addCompletionHandlers(context, std::make_tuple(std::forward<Futures>(futures)...));