summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread/qfutureinterface.cpp
diff options
context:
space:
mode:
authorSona Kurazyan <sona.kurazyan@qt.io>2021-06-07 20:15:39 +0200
committerSona Kurazyan <sona.kurazyan@qt.io>2021-06-12 03:08:59 +0200
commit6460c3c33d8f880c50e2b529827437e442d05bd3 (patch)
tree329c03c69e345296c26bb0b589eab685f2246a62 /src/corelib/thread/qfutureinterface.cpp
parente0ae1af278f3cc6df6c3f66e4118585cc8384b15 (diff)
QFuture: put the result store and the exception store in a union
QFuture doesn't need both at the same time, calling QFuture::result(s) either returns a result or throws an exception. Store result and exception stores in a union, to reduce the memory. Also added a note for making the ResultStoreBase destructor non-virtual in Qt 7. Task-number: QTBUG-92045 Change-Id: I7f0ac03804d19cc67c1a1466c7a1365219768a14 Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/corelib/thread/qfutureinterface.cpp')
-rw-r--r--src/corelib/thread/qfutureinterface.cpp73
1 files changed, 51 insertions, 22 deletions
diff --git a/src/corelib/thread/qfutureinterface.cpp b/src/corelib/thread/qfutureinterface.cpp
index 9bb7d505e2..35883d71e1 100644
--- a/src/corelib/thread/qfutureinterface.cpp
+++ b/src/corelib/thread/qfutureinterface.cpp
@@ -361,7 +361,8 @@ void QFutureInterfaceBase::reportException(const std::exception_ptr &exception)
if (d->state.loadRelaxed() & (Canceled|Finished))
return;
- d->m_exceptionStore.setException(exception);
+ d->hasException = true;
+ d->data.setException(exception);
switch_on(d->state, Canceled);
d->waitCondition.wakeAll();
d->pausedWaitCondition.wakeAll();
@@ -406,7 +407,8 @@ int QFutureInterfaceBase::loadState() const
void QFutureInterfaceBase::waitForResult(int resultIndex)
{
- d->m_exceptionStore.throwPossibleException();
+ if (d->hasException)
+ d->data.m_exceptionStore.rethrowException();
QMutexLocker lock(&d->m_mutex);
if (!isRunningOrPending())
@@ -423,7 +425,8 @@ void QFutureInterfaceBase::waitForResult(int resultIndex)
while (isRunningOrPending() && !d->internal_isResultReadyAt(waitIndex))
d->waitCondition.wait(&d->m_mutex);
- d->m_exceptionStore.throwPossibleException();
+ if (d->hasException)
+ d->data.m_exceptionStore.rethrowException();
}
void QFutureInterfaceBase::waitForFinished()
@@ -441,7 +444,8 @@ void QFutureInterfaceBase::waitForFinished()
d->waitCondition.wait(&d->m_mutex);
}
- d->m_exceptionStore.throwPossibleException();
+ if (d->hasException)
+ d->data.m_exceptionStore.rethrowException();
}
void QFutureInterfaceBase::reportResultsReady(int beginIndex, int endIndex)
@@ -488,7 +492,8 @@ QThreadPool *QFutureInterfaceBase::threadPool() const
void QFutureInterfaceBase::setFilterMode(bool enable)
{
QMutexLocker locker(&d->m_mutex);
- resultStoreBase().setFilterMode(enable);
+ if (!hasException())
+ resultStoreBase().setFilterMode(enable);
}
/*!
@@ -558,19 +563,27 @@ QMutex &QFutureInterfaceBase::mutex() const
return d->m_mutex;
}
+bool QFutureInterfaceBase::hasException() const
+{
+ return d->hasException;
+}
+
QtPrivate::ExceptionStore &QFutureInterfaceBase::exceptionStore()
{
- return d->m_exceptionStore;
+ Q_ASSERT(d->hasException);
+ return d->data.m_exceptionStore;
}
QtPrivate::ResultStoreBase &QFutureInterfaceBase::resultStoreBase()
{
- return d->m_results;
+ Q_ASSERT(!d->hasException);
+ return d->data.m_results;
}
const QtPrivate::ResultStoreBase &QFutureInterfaceBase::resultStoreBase() const
{
- return d->m_results;
+ Q_ASSERT(!d->hasException);
+ return d->data.m_results;
}
QFutureInterfaceBase &QFutureInterfaceBase::operator=(const QFutureInterfaceBase &other)
@@ -609,7 +622,8 @@ void QFutureInterfaceBase::reset()
void QFutureInterfaceBase::rethrowPossibleException()
{
- exceptionStore().throwPossibleException();
+ if (hasException())
+ exceptionStore().rethrowException();
}
QFutureInterfaceBasePrivate::QFutureInterfaceBasePrivate(QFutureInterfaceBase::State initialState)
@@ -618,25 +632,38 @@ QFutureInterfaceBasePrivate::QFutureInterfaceBasePrivate(QFutureInterfaceBase::S
progressTime.invalidate();
}
+QFutureInterfaceBasePrivate::~QFutureInterfaceBasePrivate()
+{
+ if (hasException)
+ data.m_exceptionStore.~ExceptionStore();
+ else
+ data.m_results.~ResultStoreBase();
+}
+
int QFutureInterfaceBasePrivate::internal_resultCount() const
{
- return m_results.count(); // ### subtract canceled results.
+ return hasException ? 0 : data.m_results.count(); // ### subtract canceled results.
}
bool QFutureInterfaceBasePrivate::internal_isResultReadyAt(int index) const
{
- return (m_results.contains(index));
+ return hasException ? false : (data.m_results.contains(index));
}
bool QFutureInterfaceBasePrivate::internal_waitForNextResult()
{
- if (m_results.hasNextResult())
+ if (hasException)
+ return false;
+
+ if (data.m_results.hasNextResult())
return true;
- while ((state.loadRelaxed() & QFutureInterfaceBase::Running) && m_results.hasNextResult() == false)
+ while ((state.loadRelaxed() & QFutureInterfaceBase::Running)
+ && data.m_results.hasNextResult() == false)
waitCondition.wait(&m_mutex);
- return !(state.loadRelaxed() & QFutureInterfaceBase::Canceled) && m_results.hasNextResult();
+ return !(state.loadRelaxed() & QFutureInterfaceBase::Canceled)
+ && data.m_results.hasNextResult();
}
bool QFutureInterfaceBasePrivate::internal_updateProgress(int progress,
@@ -714,14 +741,16 @@ void QFutureInterfaceBasePrivate::connectOutputInterface(QFutureCallOutInterface
m_progressText));
}
- QtPrivate::ResultIteratorBase it = m_results.begin();
- while (it != m_results.end()) {
- const int begin = it.resultIndex();
- const int end = begin + it.batchSize();
- interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::ResultsReady,
- begin,
- end));
- it.batchedAdvance();
+ if (!hasException) {
+ QtPrivate::ResultIteratorBase it = data.m_results.begin();
+ while (it != data.m_results.end()) {
+ const int begin = it.resultIndex();
+ const int end = begin + it.batchSize();
+ interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::ResultsReady,
+ begin,
+ end));
+ it.batchedAdvance();
+ }
}
if (currentState & QFutureInterfaceBase::Suspended)