From a65a98399bf45924eb4d9394cf1e905b489639cc Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 27 Aug 2012 17:23:33 +0200 Subject: Move QtConcurrent::ResultStore as QtPrivate::ResultStore to QtCore No compatibility header needed. While this wasn't marked as private API, it wasn't documented, either. This is a prerequisite for moving QFuture to QtCore. Change-Id: I8e986e6e2a22fbe5cf08d0600ec39ae9ae993e20 Reviewed-by: Thiago Macieira --- src/concurrent/concurrent.pro | 2 - src/concurrent/qfutureinterface.cpp | 6 +- src/concurrent/qfutureinterface.h | 20 +- src/concurrent/qfutureinterface_p.h | 2 +- src/concurrent/qtconcurrentresultstore.cpp | 256 ----------- src/concurrent/qtconcurrentresultstore.h | 238 ---------- src/corelib/thread/qresultstore.cpp | 256 +++++++++++ src/corelib/thread/qresultstore.h | 238 ++++++++++ src/corelib/thread/thread.pri | 2 + tests/auto/concurrent/concurrent.pro | 1 - tests/auto/concurrent/qfuture/tst_qfuture.cpp | 58 ++- .../qtconcurrentresultstore.pro | 6 - .../tst_qtconcurrentresultstore.cpp | 490 --------------------- .../corelib/thread/qresultstore/qresultstore.pro | 6 + .../thread/qresultstore/tst_qresultstore.cpp | 490 +++++++++++++++++++++ tests/auto/corelib/thread/thread.pro | 1 + 16 files changed, 1035 insertions(+), 1037 deletions(-) delete mode 100644 src/concurrent/qtconcurrentresultstore.cpp delete mode 100644 src/concurrent/qtconcurrentresultstore.h create mode 100644 src/corelib/thread/qresultstore.cpp create mode 100644 src/corelib/thread/qresultstore.h delete mode 100644 tests/auto/concurrent/qtconcurrentresultstore/qtconcurrentresultstore.pro delete mode 100644 tests/auto/concurrent/qtconcurrentresultstore/tst_qtconcurrentresultstore.cpp create mode 100644 tests/auto/corelib/thread/qresultstore/qresultstore.pro create mode 100644 tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp diff --git a/src/concurrent/concurrent.pro b/src/concurrent/concurrent.pro index 772146f682..d21dff91dd 100644 --- a/src/concurrent/concurrent.pro +++ b/src/concurrent/concurrent.pro @@ -18,7 +18,6 @@ SOURCES += \ qfuturewatcher.cpp \ qtconcurrentfilter.cpp \ qtconcurrentmap.cpp \ - qtconcurrentresultstore.cpp \ qtconcurrentthreadengine.cpp \ qtconcurrentiteratekernel.cpp \ @@ -38,7 +37,6 @@ HEADERS += \ qtconcurrentmapkernel.h \ qtconcurrentmedian.h \ qtconcurrentreducekernel.h \ - qtconcurrentresultstore.h \ qtconcurrentrun.h \ qtconcurrentrunbase.h \ qtconcurrentstoredfunctioncall.h \ diff --git a/src/concurrent/qfutureinterface.cpp b/src/concurrent/qfutureinterface.cpp index 1f675525a5..2c33418ee9 100644 --- a/src/concurrent/qfutureinterface.cpp +++ b/src/concurrent/qfutureinterface.cpp @@ -395,12 +395,12 @@ QtPrivate::ExceptionStore &QFutureInterfaceBase::exceptionStore() return d->m_exceptionStore; } -QtConcurrent::ResultStoreBase &QFutureInterfaceBase::resultStoreBase() +QtPrivate::ResultStoreBase &QFutureInterfaceBase::resultStoreBase() { return d->m_results; } -const QtConcurrent::ResultStoreBase &QFutureInterfaceBase::resultStoreBase() const +const QtPrivate::ResultStoreBase &QFutureInterfaceBase::resultStoreBase() const { return d->m_results; } @@ -522,7 +522,7 @@ void QFutureInterfaceBasePrivate::connectOutputInterface(QFutureCallOutInterface m_progressText)); } - QtConcurrent::ResultIteratorBase it = m_results.begin(); + QtPrivate::ResultIteratorBase it = m_results.begin(); while (it != m_results.end()) { const int begin = it.resultIndex(); const int end = begin + it.batchSize(); diff --git a/src/concurrent/qfutureinterface.h b/src/concurrent/qfutureinterface.h index 615b9fbe6a..e9d8d37b67 100644 --- a/src/concurrent/qfutureinterface.h +++ b/src/concurrent/qfutureinterface.h @@ -50,7 +50,7 @@ #include #include -#include +#include QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -123,8 +123,8 @@ public: QMutex *mutex() const; QtPrivate::ExceptionStore &exceptionStore(); - QtConcurrent::ResultStoreBase &resultStoreBase(); - const QtConcurrent::ResultStoreBase &resultStoreBase() const; + QtPrivate::ResultStoreBase &resultStoreBase(); + const QtPrivate::ResultStoreBase &resultStoreBase() const; inline bool operator==(const QFutureInterfaceBase &other) const { return d == other.d; } inline bool operator!=(const QFutureInterfaceBase &other) const { return d != other.d; } @@ -182,10 +182,10 @@ public: inline const T *resultPointer(int index) const; inline QList results(); private: - QtConcurrent::ResultStore &resultStore() - { return static_cast &>(resultStoreBase()); } - const QtConcurrent::ResultStore &resultStore() const - { return static_cast &>(resultStoreBase()); } + QtPrivate::ResultStore &resultStore() + { return static_cast &>(resultStoreBase()); } + const QtPrivate::ResultStore &resultStore() const + { return static_cast &>(resultStoreBase()); } }; template @@ -196,7 +196,7 @@ inline void QFutureInterface::reportResult(const T *result, int index) return; } - QtConcurrent::ResultStore &store = resultStore(); + QtPrivate::ResultStore &store = resultStore(); if (store.filterMode()) { @@ -223,7 +223,7 @@ inline void QFutureInterface::reportResults(const QVector &_results, int b return; } - QtConcurrent::ResultStore &store = resultStore(); + QtPrivate::ResultStore &store = resultStore(); if (store.filterMode()) { const int resultCountBefore = store.count(); @@ -269,7 +269,7 @@ inline QList QFutureInterface::results() QList res; QMutexLocker lock(mutex()); - QtConcurrent::ResultIterator it = resultStore().begin(); + QtPrivate::ResultIterator it = resultStore().begin(); while (it != resultStore().end()) { res.append(it.value()); ++it; diff --git a/src/concurrent/qfutureinterface_p.h b/src/concurrent/qfutureinterface_p.h index 734584adad..7fd2ea4d99 100644 --- a/src/concurrent/qfutureinterface_p.h +++ b/src/concurrent/qfutureinterface_p.h @@ -142,7 +142,7 @@ public: QElapsedTimer progressTime; QWaitCondition pausedWaitCondition; int pendingResults; - QtConcurrent::ResultStoreBase m_results; + QtPrivate::ResultStoreBase m_results; bool manualProgress; int m_expectedResultCount; QtPrivate::ExceptionStore m_exceptionStore; diff --git a/src/concurrent/qtconcurrentresultstore.cpp b/src/concurrent/qtconcurrentresultstore.cpp deleted file mode 100644 index 14a1d0f5e1..0000000000 --- a/src/concurrent/qtconcurrentresultstore.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qtconcurrentresultstore.h" - -#ifndef QT_NO_QFUTURE - -QT_BEGIN_NAMESPACE - -namespace QtConcurrent { - -ResultIteratorBase::ResultIteratorBase() - : mapIterator(QMap::const_iterator()), m_vectorIndex(0) { } -ResultIteratorBase::ResultIteratorBase(QMap::const_iterator _mapIterator, int _vectorIndex) - : mapIterator(_mapIterator), m_vectorIndex(_vectorIndex) { } - -int ResultIteratorBase::vectorIndex() const { return m_vectorIndex; } -int ResultIteratorBase::resultIndex() const { return mapIterator.key() + m_vectorIndex; } - -ResultIteratorBase ResultIteratorBase::operator++() -{ - if (canIncrementVectorIndex()) { - ++m_vectorIndex; - } else { - ++mapIterator; - m_vectorIndex = 0; - } - return *this; -} - -int ResultIteratorBase::batchSize() const -{ - return mapIterator.value().count(); -} - -void ResultIteratorBase::batchedAdvance() -{ - ++mapIterator; - m_vectorIndex = 0; -} - -bool ResultIteratorBase::operator==(const ResultIteratorBase &other) const -{ - return (mapIterator == other.mapIterator && m_vectorIndex == other.m_vectorIndex); -} - -bool ResultIteratorBase::operator!=(const ResultIteratorBase &other) const -{ - return !operator==(other); -} - -bool ResultIteratorBase::isVector() const -{ - return mapIterator.value().isVector(); -} - -bool ResultIteratorBase::canIncrementVectorIndex() const -{ - return (m_vectorIndex + 1 < mapIterator.value().m_count); -} - -ResultStoreBase::ResultStoreBase() - : insertIndex(0), resultCount(0), m_filterMode(false), filteredResults(0) { } - -void ResultStoreBase::setFilterMode(bool enable) -{ - m_filterMode = enable; -} - -bool ResultStoreBase::filterMode() const -{ - return m_filterMode; -} - -void ResultStoreBase::syncResultCount() -{ - ResultIteratorBase it = resultAt(resultCount); - while (it != end()) { - resultCount += it.batchSize(); - it = resultAt(resultCount); - } -} - -void ResultStoreBase::insertResultItemIfValid(int index, ResultItem &resultItem) -{ - if (resultItem.isValid()) { - m_results[index] = resultItem; - syncResultCount(); - } else { - filteredResults += resultItem.count(); - } -} - -int ResultStoreBase::insertResultItem(int index, ResultItem &resultItem) -{ - int storeIndex; - if (m_filterMode && index != -1 && index > insertIndex) { - pendingResults[index] = resultItem; - storeIndex = index; - } else { - storeIndex = updateInsertIndex(index, resultItem.count()); - insertResultItemIfValid(storeIndex - filteredResults, resultItem); - } - syncPendingResults(); - return storeIndex; -} - -void ResultStoreBase::syncPendingResults() -{ - // check if we can insert any of the pending results: - QMap::iterator it = pendingResults.begin(); - while (it != pendingResults.end()) { - int index = it.key(); - if (index != resultCount + filteredResults) - break; - - ResultItem result = it.value(); - insertResultItemIfValid(index - filteredResults, result); - pendingResults.erase(it); - it = pendingResults.begin(); - } -} - -int ResultStoreBase::addResult(int index, const void *result) -{ - ResultItem resultItem(result, 0); // 0 means "not a vector" - return insertResultItem(index, resultItem); -} - -int ResultStoreBase::addResults(int index, const void *results, int vectorSize, int totalCount) -{ - if (m_filterMode == false || vectorSize == totalCount) { - ResultItem resultItem(results, vectorSize); - return insertResultItem(index, resultItem); - } else { - if (vectorSize > 0) { - ResultItem filteredIn(results, vectorSize); - insertResultItem(index, filteredIn); - } - ResultItem filteredAway(0, totalCount - vectorSize); - return insertResultItem(index + vectorSize, filteredAway); - } -} - -ResultIteratorBase ResultStoreBase::begin() const -{ - return ResultIteratorBase(m_results.begin()); -} - -ResultIteratorBase ResultStoreBase::end() const -{ - return ResultIteratorBase(m_results.end()); -} - -bool ResultStoreBase::hasNextResult() const -{ - return begin() != end(); -} - -ResultIteratorBase ResultStoreBase::resultAt(int index) const -{ - if (m_results.isEmpty()) - return ResultIteratorBase(m_results.end()); - QMap::const_iterator it = m_results.lowerBound(index); - - // lowerBound returns either an iterator to the result or an iterator - // to the nearest greater index. If the latter happens it might be - // that the result is stored in a vector at the previous index. - if (it == m_results.end()) { - --it; - if (it.value().isVector() == false) { - return ResultIteratorBase(m_results.end()); - } - } else { - if (it.key() > index) { - if (it == m_results.begin()) - return ResultIteratorBase(m_results.end()); - --it; - } - } - - const int vectorIndex = index - it.key(); - - if (vectorIndex >= it.value().count()) - return ResultIteratorBase(m_results.end()); - else if (it.value().isVector() == false && vectorIndex != 0) - return ResultIteratorBase(m_results.end()); - return ResultIteratorBase(it, vectorIndex); -} - -bool ResultStoreBase::contains(int index) const -{ - return (resultAt(index) != end()); -} - -int ResultStoreBase::count() const -{ - return resultCount; -} - -// returns the insert index, calling this function with -// index equal to -1 returns the next available index. -int ResultStoreBase::updateInsertIndex(int index, int _count) -{ - if (index == -1) { - index = insertIndex; - insertIndex += _count; - } else { - insertIndex = qMax(index + _count, insertIndex); - } - return index; -} - -} // namespace QtConcurrent - -QT_END_NAMESPACE - -#endif // QT_NO_CONCURRENT diff --git a/src/concurrent/qtconcurrentresultstore.h b/src/concurrent/qtconcurrentresultstore.h deleted file mode 100644 index bc02dbf0d4..0000000000 --- a/src/concurrent/qtconcurrentresultstore.h +++ /dev/null @@ -1,238 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QTCONCURRENT_RESULTSTORE_H -#define QTCONCURRENT_RESULTSTORE_H - -#include - -#ifndef QT_NO_QFUTURE - -#include -#include - -QT_BEGIN_HEADER -QT_BEGIN_NAMESPACE - - -/* - ResultStore stores indexed results. Results can be added and retrieved - either individually batched in a QVector. Retriveing results and checking - which indexes are in the store can be done either by iterating or by random - accees. In addition results kan be removed from the front of the store, - either individually or in batches. -*/ - -#ifndef qdoc - -namespace QtConcurrent { - -class ResultItem -{ -public: - ResultItem(const void *_result, int _count) : m_count(_count), result(_result) { } // contruct with vector of results - ResultItem(const void *_result) : m_count(0), result(_result) { } // construct with result - ResultItem() : m_count(0), result(0) { } - bool isValid() const { return result != 0; } - bool isVector() const { return m_count != 0; } - int count() const { return (m_count == 0) ? 1 : m_count; } - int m_count; // result is either a pointer to a result or to a vector of results, - const void *result; // if count is 0 it's a result, otherwise it's a vector. -}; - -class Q_CONCURRENT_EXPORT ResultIteratorBase -{ -public: - ResultIteratorBase(); - ResultIteratorBase(QMap::const_iterator _mapIterator, int _vectorIndex = 0); - int vectorIndex() const; - int resultIndex() const; - - ResultIteratorBase operator++(); - int batchSize() const; - void batchedAdvance(); - bool operator==(const ResultIteratorBase &other) const; - bool operator!=(const ResultIteratorBase &other) const; - bool isVector() const; - bool canIncrementVectorIndex() const; -protected: - QMap::const_iterator mapIterator; - int m_vectorIndex; -}; - -template -class ResultIterator : public ResultIteratorBase -{ -public: - ResultIterator(const ResultIteratorBase &base) - : ResultIteratorBase(base) { } - - const T &value() const - { - return *pointer(); - } - - const T *pointer() const - { - if (mapIterator.value().isVector()) - return &(reinterpret_cast *>(mapIterator.value().result)->at(m_vectorIndex)); - else - return reinterpret_cast(mapIterator.value().result); - } -}; - -class Q_CONCURRENT_EXPORT ResultStoreBase -{ -public: - ResultStoreBase(); - void setFilterMode(bool enable); - bool filterMode() const; - int addResult(int index, const void *result); - int addResults(int index, const void *results, int vectorSize, int logicalCount); - ResultIteratorBase begin() const; - ResultIteratorBase end() const; - bool hasNextResult() const; - ResultIteratorBase resultAt(int index) const; - bool contains(int index) const; - int count() const; - virtual ~ResultStoreBase() { } - -protected: - int insertResultItem(int index, ResultItem &resultItem); - void insertResultItemIfValid(int index, ResultItem &resultItem); - void syncPendingResults(); - void syncResultCount(); - int updateInsertIndex(int index, int _count); - - QMap m_results; - int insertIndex; // The index where the next results(s) will be inserted. - int resultCount; // The number of consecutive results stored, starting at index 0. - - bool m_filterMode; - QMap pendingResults; - int filteredResults; - -}; - -template -class ResultStore : public ResultStoreBase -{ -public: - ResultStore() { } - - ResultStore(const ResultStoreBase &base) - : ResultStoreBase(base) { } - - int addResult(int index, const T *result) - { - if (result == 0) - return ResultStoreBase::addResult(index, result); - else - return ResultStoreBase::addResult(index, new T(*result)); - } - - int addResults(int index, const QVector *results) - { - return ResultStoreBase::addResults(index, new QVector(*results), results->count(), results->count()); - } - - int addResults(int index, const QVector *results, int totalCount) - { - return ResultStoreBase::addResults(index, new QVector(*results), results->count(), totalCount); - } - - int addCanceledResult(int index) - { - return addResult(index, 0); - } - - int addCanceledResults(int index, int _count) - { - QVector empty; - return addResults(index, &empty, _count); - } - - ResultIterator begin() const - { - return static_cast >(ResultStoreBase::begin()); - } - - ResultIterator end() const - { - return static_cast >(ResultStoreBase::end()); - } - - ResultIterator resultAt(int index) const - { - return static_cast >(ResultStoreBase::resultAt(index)); - } - - void clear() - { - QMap::const_iterator mapIterator = m_results.constBegin(); - while (mapIterator != m_results.constEnd()) { - if (mapIterator.value().isVector()) - delete reinterpret_cast *>(mapIterator.value().result); - else - delete reinterpret_cast(mapIterator.value().result); - ++mapIterator; - } - resultCount = 0; - m_results.clear(); - } - - ~ResultStore() - { - clear(); - } - -}; - -} // namespace QtConcurrent - -#endif //qdoc - -QT_END_NAMESPACE -QT_END_HEADER - -#endif // QT_NO_CONCURRENT - -#endif diff --git a/src/corelib/thread/qresultstore.cpp b/src/corelib/thread/qresultstore.cpp new file mode 100644 index 0000000000..93a8d456b8 --- /dev/null +++ b/src/corelib/thread/qresultstore.cpp @@ -0,0 +1,256 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qresultstore.h" + +#ifndef QT_NO_QFUTURE + +QT_BEGIN_NAMESPACE + +namespace QtPrivate { + +ResultIteratorBase::ResultIteratorBase() + : mapIterator(QMap::const_iterator()), m_vectorIndex(0) { } +ResultIteratorBase::ResultIteratorBase(QMap::const_iterator _mapIterator, int _vectorIndex) + : mapIterator(_mapIterator), m_vectorIndex(_vectorIndex) { } + +int ResultIteratorBase::vectorIndex() const { return m_vectorIndex; } +int ResultIteratorBase::resultIndex() const { return mapIterator.key() + m_vectorIndex; } + +ResultIteratorBase ResultIteratorBase::operator++() +{ + if (canIncrementVectorIndex()) { + ++m_vectorIndex; + } else { + ++mapIterator; + m_vectorIndex = 0; + } + return *this; +} + +int ResultIteratorBase::batchSize() const +{ + return mapIterator.value().count(); +} + +void ResultIteratorBase::batchedAdvance() +{ + ++mapIterator; + m_vectorIndex = 0; +} + +bool ResultIteratorBase::operator==(const ResultIteratorBase &other) const +{ + return (mapIterator == other.mapIterator && m_vectorIndex == other.m_vectorIndex); +} + +bool ResultIteratorBase::operator!=(const ResultIteratorBase &other) const +{ + return !operator==(other); +} + +bool ResultIteratorBase::isVector() const +{ + return mapIterator.value().isVector(); +} + +bool ResultIteratorBase::canIncrementVectorIndex() const +{ + return (m_vectorIndex + 1 < mapIterator.value().m_count); +} + +ResultStoreBase::ResultStoreBase() + : insertIndex(0), resultCount(0), m_filterMode(false), filteredResults(0) { } + +void ResultStoreBase::setFilterMode(bool enable) +{ + m_filterMode = enable; +} + +bool ResultStoreBase::filterMode() const +{ + return m_filterMode; +} + +void ResultStoreBase::syncResultCount() +{ + ResultIteratorBase it = resultAt(resultCount); + while (it != end()) { + resultCount += it.batchSize(); + it = resultAt(resultCount); + } +} + +void ResultStoreBase::insertResultItemIfValid(int index, ResultItem &resultItem) +{ + if (resultItem.isValid()) { + m_results[index] = resultItem; + syncResultCount(); + } else { + filteredResults += resultItem.count(); + } +} + +int ResultStoreBase::insertResultItem(int index, ResultItem &resultItem) +{ + int storeIndex; + if (m_filterMode && index != -1 && index > insertIndex) { + pendingResults[index] = resultItem; + storeIndex = index; + } else { + storeIndex = updateInsertIndex(index, resultItem.count()); + insertResultItemIfValid(storeIndex - filteredResults, resultItem); + } + syncPendingResults(); + return storeIndex; +} + +void ResultStoreBase::syncPendingResults() +{ + // check if we can insert any of the pending results: + QMap::iterator it = pendingResults.begin(); + while (it != pendingResults.end()) { + int index = it.key(); + if (index != resultCount + filteredResults) + break; + + ResultItem result = it.value(); + insertResultItemIfValid(index - filteredResults, result); + pendingResults.erase(it); + it = pendingResults.begin(); + } +} + +int ResultStoreBase::addResult(int index, const void *result) +{ + ResultItem resultItem(result, 0); // 0 means "not a vector" + return insertResultItem(index, resultItem); +} + +int ResultStoreBase::addResults(int index, const void *results, int vectorSize, int totalCount) +{ + if (m_filterMode == false || vectorSize == totalCount) { + ResultItem resultItem(results, vectorSize); + return insertResultItem(index, resultItem); + } else { + if (vectorSize > 0) { + ResultItem filteredIn(results, vectorSize); + insertResultItem(index, filteredIn); + } + ResultItem filteredAway(0, totalCount - vectorSize); + return insertResultItem(index + vectorSize, filteredAway); + } +} + +ResultIteratorBase ResultStoreBase::begin() const +{ + return ResultIteratorBase(m_results.begin()); +} + +ResultIteratorBase ResultStoreBase::end() const +{ + return ResultIteratorBase(m_results.end()); +} + +bool ResultStoreBase::hasNextResult() const +{ + return begin() != end(); +} + +ResultIteratorBase ResultStoreBase::resultAt(int index) const +{ + if (m_results.isEmpty()) + return ResultIteratorBase(m_results.end()); + QMap::const_iterator it = m_results.lowerBound(index); + + // lowerBound returns either an iterator to the result or an iterator + // to the nearest greater index. If the latter happens it might be + // that the result is stored in a vector at the previous index. + if (it == m_results.end()) { + --it; + if (it.value().isVector() == false) { + return ResultIteratorBase(m_results.end()); + } + } else { + if (it.key() > index) { + if (it == m_results.begin()) + return ResultIteratorBase(m_results.end()); + --it; + } + } + + const int vectorIndex = index - it.key(); + + if (vectorIndex >= it.value().count()) + return ResultIteratorBase(m_results.end()); + else if (it.value().isVector() == false && vectorIndex != 0) + return ResultIteratorBase(m_results.end()); + return ResultIteratorBase(it, vectorIndex); +} + +bool ResultStoreBase::contains(int index) const +{ + return (resultAt(index) != end()); +} + +int ResultStoreBase::count() const +{ + return resultCount; +} + +// returns the insert index, calling this function with +// index equal to -1 returns the next available index. +int ResultStoreBase::updateInsertIndex(int index, int _count) +{ + if (index == -1) { + index = insertIndex; + insertIndex += _count; + } else { + insertIndex = qMax(index + _count, insertIndex); + } + return index; +} + +} // namespace QtPrivate + +QT_END_NAMESPACE + +#endif // QT_NO_QFUTURE diff --git a/src/corelib/thread/qresultstore.h b/src/corelib/thread/qresultstore.h new file mode 100644 index 0000000000..3314cd7aaf --- /dev/null +++ b/src/corelib/thread/qresultstore.h @@ -0,0 +1,238 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTCORE_RESULTSTORE_H +#define QTCORE_RESULTSTORE_H + +#include + +#ifndef QT_NO_QFUTURE + +#include +#include + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + + +/* + ResultStore stores indexed results. Results can be added and retrieved + either individually batched in a QVector. Retriveing results and checking + which indexes are in the store can be done either by iterating or by random + accees. In addition results kan be removed from the front of the store, + either individually or in batches. +*/ + +#ifndef qdoc + +namespace QtPrivate { + +class ResultItem +{ +public: + ResultItem(const void *_result, int _count) : m_count(_count), result(_result) { } // contruct with vector of results + ResultItem(const void *_result) : m_count(0), result(_result) { } // construct with result + ResultItem() : m_count(0), result(0) { } + bool isValid() const { return result != 0; } + bool isVector() const { return m_count != 0; } + int count() const { return (m_count == 0) ? 1 : m_count; } + int m_count; // result is either a pointer to a result or to a vector of results, + const void *result; // if count is 0 it's a result, otherwise it's a vector. +}; + +class Q_CORE_EXPORT ResultIteratorBase +{ +public: + ResultIteratorBase(); + ResultIteratorBase(QMap::const_iterator _mapIterator, int _vectorIndex = 0); + int vectorIndex() const; + int resultIndex() const; + + ResultIteratorBase operator++(); + int batchSize() const; + void batchedAdvance(); + bool operator==(const ResultIteratorBase &other) const; + bool operator!=(const ResultIteratorBase &other) const; + bool isVector() const; + bool canIncrementVectorIndex() const; +protected: + QMap::const_iterator mapIterator; + int m_vectorIndex; +}; + +template +class ResultIterator : public ResultIteratorBase +{ +public: + ResultIterator(const ResultIteratorBase &base) + : ResultIteratorBase(base) { } + + const T &value() const + { + return *pointer(); + } + + const T *pointer() const + { + if (mapIterator.value().isVector()) + return &(reinterpret_cast *>(mapIterator.value().result)->at(m_vectorIndex)); + else + return reinterpret_cast(mapIterator.value().result); + } +}; + +class Q_CORE_EXPORT ResultStoreBase +{ +public: + ResultStoreBase(); + void setFilterMode(bool enable); + bool filterMode() const; + int addResult(int index, const void *result); + int addResults(int index, const void *results, int vectorSize, int logicalCount); + ResultIteratorBase begin() const; + ResultIteratorBase end() const; + bool hasNextResult() const; + ResultIteratorBase resultAt(int index) const; + bool contains(int index) const; + int count() const; + virtual ~ResultStoreBase() { } + +protected: + int insertResultItem(int index, ResultItem &resultItem); + void insertResultItemIfValid(int index, ResultItem &resultItem); + void syncPendingResults(); + void syncResultCount(); + int updateInsertIndex(int index, int _count); + + QMap m_results; + int insertIndex; // The index where the next results(s) will be inserted. + int resultCount; // The number of consecutive results stored, starting at index 0. + + bool m_filterMode; + QMap pendingResults; + int filteredResults; + +}; + +template +class ResultStore : public ResultStoreBase +{ +public: + ResultStore() { } + + ResultStore(const ResultStoreBase &base) + : ResultStoreBase(base) { } + + int addResult(int index, const T *result) + { + if (result == 0) + return ResultStoreBase::addResult(index, result); + else + return ResultStoreBase::addResult(index, new T(*result)); + } + + int addResults(int index, const QVector *results) + { + return ResultStoreBase::addResults(index, new QVector(*results), results->count(), results->count()); + } + + int addResults(int index, const QVector *results, int totalCount) + { + return ResultStoreBase::addResults(index, new QVector(*results), results->count(), totalCount); + } + + int addCanceledResult(int index) + { + return addResult(index, 0); + } + + int addCanceledResults(int index, int _count) + { + QVector empty; + return addResults(index, &empty, _count); + } + + ResultIterator begin() const + { + return static_cast >(ResultStoreBase::begin()); + } + + ResultIterator end() const + { + return static_cast >(ResultStoreBase::end()); + } + + ResultIterator resultAt(int index) const + { + return static_cast >(ResultStoreBase::resultAt(index)); + } + + void clear() + { + QMap::const_iterator mapIterator = m_results.constBegin(); + while (mapIterator != m_results.constEnd()) { + if (mapIterator.value().isVector()) + delete reinterpret_cast *>(mapIterator.value().result); + else + delete reinterpret_cast(mapIterator.value().result); + ++mapIterator; + } + resultCount = 0; + m_results.clear(); + } + + ~ResultStore() + { + clear(); + } + +}; + +} // namespace QtPrivate + +#endif //qdoc + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // QT_NO_QFUTURE + +#endif diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri index 215e56628c..d9468cc3a4 100644 --- a/src/corelib/thread/thread.pri +++ b/src/corelib/thread/thread.pri @@ -11,6 +11,7 @@ HEADERS += thread/qmutex.h \ thread/qwaitcondition.h \ thread/qatomic.h \ thread/qexception.h \ + thread/qresultstore.h \ thread/qbasicatomic.h \ thread/qgenericatomic.h \ thread/qoldbasicatomic.h @@ -25,6 +26,7 @@ HEADERS += thread/qmutex_p.h \ SOURCES += thread/qatomic.cpp \ thread/qexception.cpp \ + thread/qresultstore.cpp \ thread/qmutex.cpp \ thread/qreadwritelock.cpp \ thread/qrunnable.cpp \ diff --git a/tests/auto/concurrent/concurrent.pro b/tests/auto/concurrent/concurrent.pro index 15368aef64..c87ae9e673 100644 --- a/tests/auto/concurrent/concurrent.pro +++ b/tests/auto/concurrent/concurrent.pro @@ -6,7 +6,6 @@ SUBDIRS=\ qtconcurrentfilter \ qtconcurrentiteratekernel \ qtconcurrentmap \ - qtconcurrentresultstore \ qtconcurrentrun \ qtconcurrentthreadengine diff --git a/tests/auto/concurrent/qfuture/tst_qfuture.cpp b/tests/auto/concurrent/qfuture/tst_qfuture.cpp index aea35e80b2..ebf545f128 100644 --- a/tests/auto/concurrent/qfuture/tst_qfuture.cpp +++ b/tests/auto/concurrent/qfuture/tst_qfuture.cpp @@ -46,12 +46,10 @@ #include #include #include -#include -#include +#include +#include #include -using namespace QtConcurrent; - // COM interface macro. #if defined(Q_OS_WIN) && defined(interface) # undef interface @@ -91,7 +89,7 @@ void tst_QFuture::resultStore() int int2 = 2; { - ResultStore store; + QtPrivate::ResultStore store; QVERIFY(store.begin() == store.end()); QVERIFY(store.resultAt(0) == store.end()); QVERIFY(store.resultAt(1) == store.end()); @@ -99,10 +97,10 @@ void tst_QFuture::resultStore() { - ResultStoreBase store; + QtPrivate::ResultStoreBase store; store.addResult(-1, &int0); // note to self: adding a pointer to the stack here is ok since store.addResult(1, &int1); // ResultStoreBase does not take ownership, only ResultStore<> does. - ResultIteratorBase it = store.begin(); + QtPrivate::ResultIteratorBase it = store.begin(); QCOMPARE(it.resultIndex(), 0); QVERIFY(it == store.begin()); QVERIFY(it != store.end()); @@ -121,10 +119,10 @@ void tst_QFuture::resultStore() QVector vec1 = QVector() << 4 << 5; { - ResultStoreBase store; + QtPrivate::ResultStoreBase store; store.addResults(-1, &vec0, 2, 2); store.addResults(-1, &vec1, 2, 2); - ResultIteratorBase it = store.begin(); + QtPrivate::ResultIteratorBase it = store.begin(); QCOMPARE(it.resultIndex(), 0); QVERIFY(it == store.begin()); QVERIFY(it != store.end()); @@ -144,12 +142,12 @@ void tst_QFuture::resultStore() QVERIFY(it == store.end()); } { - ResultStoreBase store; + QtPrivate::ResultStoreBase store; store.addResult(-1, &int0); store.addResults(-1, &vec1, 2, 2); store.addResult(-1, &int1); - ResultIteratorBase it = store.begin(); + QtPrivate::ResultIteratorBase it = store.begin(); QCOMPARE(it.resultIndex(), 0); QVERIFY(it == store.begin()); QVERIFY(it != store.end()); @@ -175,12 +173,12 @@ void tst_QFuture::resultStore() QCOMPARE(store.resultAt(4), store.end()); } { - ResultStore store; + QtPrivate::ResultStore store; store.addResult(-1, &int0); store.addResults(-1, &vec0); store.addResult(-1, &int1); - ResultIteratorBase it = store.begin(); + QtPrivate::ResultIteratorBase it = store.begin(); QCOMPARE(it.resultIndex(), 0); QVERIFY(it == store.begin()); QVERIFY(it != store.end()); @@ -205,7 +203,7 @@ void tst_QFuture::resultStore() QCOMPARE(store.resultAt(3).value(), int1); } { - ResultStore store; + QtPrivate::ResultStore store; store.addResult(-1, &int0); store.addResults(-1, &vec0); store.addResult(200, &int1); @@ -217,7 +215,7 @@ void tst_QFuture::resultStore() } { - ResultStore store; + QtPrivate::ResultStore store; store.addResult(1, &int1); store.addResult(0, &int0); store.addResult(-1, &int2); @@ -228,7 +226,7 @@ void tst_QFuture::resultStore() } { - ResultStore store; + QtPrivate::ResultStore store; QCOMPARE(store.contains(0), false); QCOMPARE(store.contains(1), false); QCOMPARE(store.contains(INT_MAX), false); @@ -236,7 +234,7 @@ void tst_QFuture::resultStore() { // Test filter mode, where "gaps" in the result array aren't allowed. - ResultStore store; + QtPrivate::ResultStore store; store.setFilterMode(true); store.addResult(0, &int0); @@ -270,7 +268,7 @@ void tst_QFuture::resultStore() { // test canceled results - ResultStore store; + QtPrivate::ResultStore store; store.setFilterMode(true); store.addResult(0, &int0); @@ -307,7 +305,7 @@ void tst_QFuture::resultStore() { // test addResult return value - ResultStore store; + QtPrivate::ResultStore store; store.setFilterMode(true); store.addResult(0, &int0); @@ -353,7 +351,7 @@ void tst_QFuture::resultStore() { // test resultCount in non-filtered mode. It should always be possible // to iterate through the results 0 to resultCount. - ResultStore store; + QtPrivate::ResultStore store; store.addResult(0, &int0); QCOMPARE(store.count(), 1); @@ -367,7 +365,7 @@ void tst_QFuture::resultStore() } { - ResultStore store; + QtPrivate::ResultStore store; store.addResult(2, &int0); QCOMPARE(store.count(), 0); @@ -379,7 +377,7 @@ void tst_QFuture::resultStore() } { - ResultStore store; + QtPrivate::ResultStore store; store.addResults(2, &vec1); QCOMPARE(store.count(), 0); @@ -391,7 +389,7 @@ void tst_QFuture::resultStore() } { - ResultStore store; + QtPrivate::ResultStore store; store.addResults(2, &vec1); QCOMPARE(store.count(), 0); @@ -399,7 +397,7 @@ void tst_QFuture::resultStore() QCOMPARE(store.count(), 4); } { - ResultStore store; + QtPrivate::ResultStore store; store.addResults(3, &vec1); QCOMPARE(store.count(), 0); @@ -411,7 +409,7 @@ void tst_QFuture::resultStore() } { - ResultStore store; + QtPrivate::ResultStore store; store.setFilterMode(true); store.addResults(3, &vec1); QCOMPARE(store.count(), 0); @@ -424,7 +422,7 @@ void tst_QFuture::resultStore() } { - ResultStore store; + QtPrivate::ResultStore store; store.setFilterMode(true); store.addResults(3, &vec1); QCOMPARE(store.count(), 0); @@ -434,7 +432,7 @@ void tst_QFuture::resultStore() } { - ResultStore store; + QtPrivate::ResultStore store; store.setFilterMode(true); store.addResults(3, &vec1); QCOMPARE(store.count(), 0); @@ -447,7 +445,7 @@ void tst_QFuture::resultStore() } { - ResultStore store; + QtPrivate::ResultStore store; store.addResult(1, &int0); store.addResult(3, &int0); store.addResults(6, &vec0); @@ -462,7 +460,7 @@ void tst_QFuture::resultStore() } { - ResultStore store; + QtPrivate::ResultStore store; store.setFilterMode(true); store.addResult(1, &int0); store.addResult(3, &int0); @@ -490,7 +488,7 @@ void tst_QFuture::resultStore() QCOMPARE(store.contains(7), false); } { - ResultStore store; + QtPrivate::ResultStore store; store.setFilterMode(true); store.addCanceledResult(0); QCOMPARE(store.contains(0), false); diff --git a/tests/auto/concurrent/qtconcurrentresultstore/qtconcurrentresultstore.pro b/tests/auto/concurrent/qtconcurrentresultstore/qtconcurrentresultstore.pro deleted file mode 100644 index 02fed4e04c..0000000000 --- a/tests/auto/concurrent/qtconcurrentresultstore/qtconcurrentresultstore.pro +++ /dev/null @@ -1,6 +0,0 @@ -CONFIG += testcase parallel_test -TARGET = tst_qtconcurrentresultstore -QT = core-private testlib concurrent -SOURCES = tst_qtconcurrentresultstore.cpp -DEFINES += QT_STRICT_ITERATORS -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/concurrent/qtconcurrentresultstore/tst_qtconcurrentresultstore.cpp b/tests/auto/concurrent/qtconcurrentresultstore/tst_qtconcurrentresultstore.cpp deleted file mode 100644 index cf833ba4f8..0000000000 --- a/tests/auto/concurrent/qtconcurrentresultstore/tst_qtconcurrentresultstore.cpp +++ /dev/null @@ -1,490 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include - -#include - -using namespace QtConcurrent; - -class tst_QtConcurrentResultStore : public QObject -{ - Q_OBJECT -public slots: - void init(); -private slots: - void construction(); - void iterators(); - void addResult(); - void addResults(); - void resultIndex(); - void resultAt(); - void contains(); - void filterMode(); - void addCanceledResult(); - void count(); -private: - int int0; - int int1; - int int2; - QVector vec0; - QVector vec1; -}; - -void tst_QtConcurrentResultStore::init() -{ - int0 = 0; - int1 = 1; - int2 = 2; - vec0 = QVector() << 2 << 3; - vec1 = QVector() << 4 << 5; -} - -void tst_QtConcurrentResultStore::construction() -{ - ResultStore store; - QCOMPARE(store.count(), 0); -} - -void tst_QtConcurrentResultStore::iterators() -{ - { - ResultStore store; - QVERIFY(store.begin() == store.end()); - QVERIFY(store.resultAt(0) == store.end()); - QVERIFY(store.resultAt(1) == store.end()); - } - { - ResultStoreBase storebase; - storebase.addResult(-1, &int0); // note to self: adding a pointer to the stack here is ok since - storebase.addResult(1, &int1); // ResultStoreBase does not take ownership, only ResultStore<> does. - ResultIteratorBase it = storebase.begin(); - QCOMPARE(it.resultIndex(), 0); - QVERIFY(it == storebase.begin()); - QVERIFY(it != storebase.end()); - - ++it; - QCOMPARE(it.resultIndex(), 1); - QVERIFY(it != storebase.begin()); - QVERIFY(it != storebase.end()); - - ++it; - QVERIFY(it != storebase.begin()); - QVERIFY(it == storebase.end()); - } -} - -void tst_QtConcurrentResultStore::addResult() -{ - { - // test addResult return value - ResultStore store; - store.setFilterMode(true); - - QCOMPARE(store.addResult(0, &int0), 0); - QCOMPARE(store.count(), 1); // result 0 becomes available - QCOMPARE(store.contains(0), true); - - QCOMPARE(store.addResult(2, &int0), 2); - QCOMPARE(store.count(), 1); - QCOMPARE(store.contains(2), false); - - QCOMPARE(store.addCanceledResult(1), 1); - QCOMPARE(store.count(), 2); // result 2 is renamed to 1 and becomes available - - QCOMPARE(store.contains(0), true); - QCOMPARE(store.contains(1), true); - QCOMPARE(store.contains(2), false); - - QCOMPARE(store.addResult(3, &int0), 3); - QCOMPARE(store.count(), 3); - QCOMPARE(store.contains(2), true); - - QCOMPARE(store.addResult(6, &int0), 6); - QCOMPARE(store.count(), 3); - QCOMPARE(store.addResult(7, &int0), 7); - QCOMPARE(store.count(), 3); - QCOMPARE(store.contains(3), false); - - QCOMPARE(store.addCanceledResult(4), 4); - QCOMPARE(store.addCanceledResult(5), 5); - QCOMPARE(store.count(), 5); // 6 and 7 is renamed to 3 and 4 and becomes available - - QCOMPARE(store.contains(3), true); - QCOMPARE(store.contains(4), true); - - QCOMPARE(store.addResult(8, &int0), 8); - QCOMPARE(store.contains(5), true); - QCOMPARE(store.count(), 6); - - QCOMPARE(store.contains(6), false); - QCOMPARE(store.contains(7), false); - } -} - -void tst_QtConcurrentResultStore::addResults() -{ - - ResultStoreBase store; - store.addResults(-1, &vec0, 2, 2); - store.addResults(-1, &vec1, 2, 2); - ResultIteratorBase it = store.begin(); - QCOMPARE(it.resultIndex(), 0); - QVERIFY(it == store.begin()); - QVERIFY(it != store.end()); - - ++it; - QCOMPARE(it.resultIndex(), 1); - QVERIFY(it != store.begin()); - QVERIFY(it != store.end()); - - ++it; - QCOMPARE(it.resultIndex(), 2); - - ++it; - QCOMPARE(it.resultIndex(), 3); - - ++it; - QVERIFY(it == store.end()); -} - -void tst_QtConcurrentResultStore::resultIndex() -{ - ResultStore store; - store.addResult(-1, &int0); - store.addResults(-1, &vec0); - store.addResult(-1, &int1); - - ResultIteratorBase it = store.begin(); - QCOMPARE(it.resultIndex(), 0); - QVERIFY(it == store.begin()); - QVERIFY(it != store.end()); - - ++it; - QCOMPARE(it.resultIndex(), 1); - QVERIFY(it != store.begin()); - QVERIFY(it != store.end()); - - ++it; - QCOMPARE(it.resultIndex(), 2); - QVERIFY(it != store.end()); - ++it; - QCOMPARE(it.resultIndex(), 3); - QVERIFY(it != store.end()); - ++it; - QVERIFY(it == store.end()); - - QCOMPARE(store.resultAt(0).value(), int0); - QCOMPARE(store.resultAt(1).value(), vec0[0]); - QCOMPARE(store.resultAt(2).value(), vec0[1]); - QCOMPARE(store.resultAt(3).value(), int1); -} - -void tst_QtConcurrentResultStore::resultAt() -{ - { - ResultStore store; - store.addResult(-1, &int0); - store.addResults(-1, &vec0); - store.addResult(200, &int1); - - QCOMPARE(store.resultAt(0).value(), int0); - QCOMPARE(store.resultAt(1).value(), vec0[0]); - QCOMPARE(store.resultAt(2).value(), vec0[1]); - QCOMPARE(store.resultAt(200).value(), int1); - } - { - ResultStore store; - store.addResult(1, &int1); - store.addResult(0, &int0); - store.addResult(-1, &int2); - - QCOMPARE(store.resultAt(0).value(), int0); - QCOMPARE(store.resultAt(1).value(), int1); - QCOMPARE(store.resultAt(2).value(), int2); - } -} - -void tst_QtConcurrentResultStore::contains() -{ - { - ResultStore store; - QCOMPARE(store.contains(0), false); - QCOMPARE(store.contains(1), false); - QCOMPARE(store.contains(INT_MAX), false); - store.addResult(1, &int1); - QVERIFY(store.contains(int1)); - store.addResult(0, &int0); - QVERIFY(store.contains(int0)); - store.addResult(-1, &int2); - QVERIFY(store.contains(int2)); - } - { - ResultStore store; - store.addResult(1, &int0); - store.addResult(3, &int0); - store.addResults(6, &vec0); - QCOMPARE(store.contains(0), false); - QCOMPARE(store.contains(1), true); - QCOMPARE(store.contains(2), false); - QCOMPARE(store.contains(3), true); - QCOMPARE(store.contains(4), false); - QCOMPARE(store.contains(5), false); - QCOMPARE(store.contains(6), true); - QCOMPARE(store.contains(7), true); - } - - { - ResultStore store; - store.setFilterMode(true); - store.addResult(1, &int0); - store.addResult(3, &int0); - store.addResults(6, &vec0); - QCOMPARE(store.contains(0), false); - QCOMPARE(store.contains(1), false); - QCOMPARE(store.contains(2), false); - QCOMPARE(store.contains(3), false); - QCOMPARE(store.contains(4), false); - QCOMPARE(store.contains(5), false); - QCOMPARE(store.contains(6), false); - QCOMPARE(store.contains(7), false); - - store.addCanceledResult(0); - store.addCanceledResult(2); - store.addCanceledResults(4, 2); - - QCOMPARE(store.contains(0), true); - QCOMPARE(store.contains(1), true); - QCOMPARE(store.contains(2), true); - QCOMPARE(store.contains(3), true); - QCOMPARE(store.contains(4), false); - QCOMPARE(store.contains(5), false); - QCOMPARE(store.contains(6), false); - QCOMPARE(store.contains(7), false); - } - { - ResultStore store; - store.setFilterMode(true); - store.addCanceledResult(0); - QCOMPARE(store.contains(0), false); - - store.addResult(1, &int0); - QCOMPARE(store.contains(0), true); - QCOMPARE(store.contains(1), false); - } -} - -void tst_QtConcurrentResultStore::filterMode() -{ - // Test filter mode, where "gaps" in the result array aren't allowed. - ResultStore store; - QCOMPARE(store.filterMode(), false); - store.setFilterMode(true); - QVERIFY(store.filterMode()); - - store.addResult(0, &int0); - QCOMPARE(store.contains(0), true); - - store.addResult(2, &int2); // add result at index 2 - QCOMPARE(store.contains(2), false); // but 1 is missing, so this 2 won't be reported yet. - - store.addResult(1, &int1); - QCOMPARE(store.contains(1), true); - QCOMPARE(store.contains(2), true); // 2 should be visible now. - - store.addResult(4, &int0); - store.addResult(5, &int0); - store.addResult(7, &int0); - QCOMPARE(store.contains(4), false); - QCOMPARE(store.contains(5), false); - QCOMPARE(store.contains(7), false); - - store.addResult(3, &int0); // adding 3 makes 4 and 5 visible - QCOMPARE(store.contains(4), true); - QCOMPARE(store.contains(5), true); - QCOMPARE(store.contains(7), false); - - store.addResult(6, &int0); // adding 6 makes 7 visible - - QCOMPARE(store.contains(6), true); - QCOMPARE(store.contains(7), true); - QCOMPARE(store.contains(8), false); -} - -void tst_QtConcurrentResultStore::addCanceledResult() -{ - // test canceled results - ResultStore store; - store.setFilterMode(true); - - store.addResult(0, &int0); - QCOMPARE(store.contains(0), true); - - store.addResult(2, &int0); - QCOMPARE(store.contains(2), false); - - store.addCanceledResult(1); // report no result at 1 - - QCOMPARE(store.contains(0), true); - QCOMPARE(store.contains(1), true); // 2 gets renamed to 1 - QCOMPARE(store.contains(2), false); - - store.addResult(3, &int0); - QCOMPARE(store.contains(2), true); //3 gets renamed to 2 - - store.addResult(6, &int0); - store.addResult(7, &int0); - QCOMPARE(store.contains(3), false); - - store.addCanceledResult(4); - store.addCanceledResult(5); - - QCOMPARE(store.contains(3), true); //6 gets renamed to 3 - QCOMPARE(store.contains(4), true); //7 gets renamed to 4 - - store.addResult(8, &int0); - QCOMPARE(store.contains(5), true); //8 gets renamed to 4 - - QCOMPARE(store.contains(6), false); - QCOMPARE(store.contains(7), false); -} - -void tst_QtConcurrentResultStore::count() -{ - { - // test resultCount in non-filtered mode. It should always be possible - // to iterate through the results 0 to resultCount. - ResultStore store; - store.addResult(0, &int0); - - QCOMPARE(store.count(), 1); - - store.addResult(2, &int0); - - QCOMPARE(store.count(), 1); - - store.addResult(1, &int0); - QCOMPARE(store.count(), 3); - } - - { - ResultStore store; - store.addResult(2, &int0); - QCOMPARE(store.count(), 0); - - store.addResult(1, &int0); - QCOMPARE(store.count(), 0); - - store.addResult(0, &int0); - QCOMPARE(store.count(), 3); - } - - { - ResultStore store; - store.addResults(2, &vec1); - QCOMPARE(store.count(), 0); - - store.addResult(1, &int0); - QCOMPARE(store.count(), 0); - - store.addResult(0, &int0); - QCOMPARE(store.count(), 4); - } - - { - ResultStore store; - store.addResults(2, &vec1); - QCOMPARE(store.count(), 0); - - store.addResults(0, &vec0); - QCOMPARE(store.count(), 4); - } - { - ResultStore store; - store.addResults(3, &vec1); - QCOMPARE(store.count(), 0); - - store.addResults(0, &vec0); - QCOMPARE(store.count(), 2); - - store.addResult(2, &int0); - QCOMPARE(store.count(), 5); - } - - { - ResultStore store; - store.setFilterMode(true); - store.addResults(3, &vec1); - QCOMPARE(store.count(), 0); - - store.addResults(0, &vec0); - QCOMPARE(store.count(), 2); - - store.addCanceledResult(2); - QCOMPARE(store.count(), 4); - } - - { - ResultStore store; - store.setFilterMode(true); - store.addResults(3, &vec1); - QCOMPARE(store.count(), 0); - - store.addCanceledResults(0, 3); - QCOMPARE(store.count(), 2); - } - - { - ResultStore store; - store.setFilterMode(true); - store.addResults(3, &vec1); - QCOMPARE(store.count(), 0); - - store.addCanceledResults(0, 3); - QCOMPARE(store.count(), 2); // results at 3 and 4 become available at index 0, 1 - - store.addResult(5, &int0); - QCOMPARE(store.count(), 3);// result 5 becomes available at index 2 - } -} - -QTEST_MAIN(tst_QtConcurrentResultStore) -#include "tst_qtconcurrentresultstore.moc" diff --git a/tests/auto/corelib/thread/qresultstore/qresultstore.pro b/tests/auto/corelib/thread/qresultstore/qresultstore.pro new file mode 100644 index 0000000000..5e9e83c503 --- /dev/null +++ b/tests/auto/corelib/thread/qresultstore/qresultstore.pro @@ -0,0 +1,6 @@ +CONFIG += testcase parallel_test +TARGET = tst_qresultstore +QT = core-private testlib concurrent +SOURCES = tst_qresultstore.cpp +DEFINES += QT_STRICT_ITERATORS +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp b/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp new file mode 100644 index 0000000000..a28be46dda --- /dev/null +++ b/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp @@ -0,0 +1,490 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include + +using namespace QtPrivate; + +class tst_QtConcurrentResultStore : public QObject +{ + Q_OBJECT +public slots: + void init(); +private slots: + void construction(); + void iterators(); + void addResult(); + void addResults(); + void resultIndex(); + void resultAt(); + void contains(); + void filterMode(); + void addCanceledResult(); + void count(); +private: + int int0; + int int1; + int int2; + QVector vec0; + QVector vec1; +}; + +void tst_QtConcurrentResultStore::init() +{ + int0 = 0; + int1 = 1; + int2 = 2; + vec0 = QVector() << 2 << 3; + vec1 = QVector() << 4 << 5; +} + +void tst_QtConcurrentResultStore::construction() +{ + ResultStore store; + QCOMPARE(store.count(), 0); +} + +void tst_QtConcurrentResultStore::iterators() +{ + { + ResultStore store; + QVERIFY(store.begin() == store.end()); + QVERIFY(store.resultAt(0) == store.end()); + QVERIFY(store.resultAt(1) == store.end()); + } + { + ResultStoreBase storebase; + storebase.addResult(-1, &int0); // note to self: adding a pointer to the stack here is ok since + storebase.addResult(1, &int1); // ResultStoreBase does not take ownership, only ResultStore<> does. + ResultIteratorBase it = storebase.begin(); + QCOMPARE(it.resultIndex(), 0); + QVERIFY(it == storebase.begin()); + QVERIFY(it != storebase.end()); + + ++it; + QCOMPARE(it.resultIndex(), 1); + QVERIFY(it != storebase.begin()); + QVERIFY(it != storebase.end()); + + ++it; + QVERIFY(it != storebase.begin()); + QVERIFY(it == storebase.end()); + } +} + +void tst_QtConcurrentResultStore::addResult() +{ + { + // test addResult return value + ResultStore store; + store.setFilterMode(true); + + QCOMPARE(store.addResult(0, &int0), 0); + QCOMPARE(store.count(), 1); // result 0 becomes available + QCOMPARE(store.contains(0), true); + + QCOMPARE(store.addResult(2, &int0), 2); + QCOMPARE(store.count(), 1); + QCOMPARE(store.contains(2), false); + + QCOMPARE(store.addCanceledResult(1), 1); + QCOMPARE(store.count(), 2); // result 2 is renamed to 1 and becomes available + + QCOMPARE(store.contains(0), true); + QCOMPARE(store.contains(1), true); + QCOMPARE(store.contains(2), false); + + QCOMPARE(store.addResult(3, &int0), 3); + QCOMPARE(store.count(), 3); + QCOMPARE(store.contains(2), true); + + QCOMPARE(store.addResult(6, &int0), 6); + QCOMPARE(store.count(), 3); + QCOMPARE(store.addResult(7, &int0), 7); + QCOMPARE(store.count(), 3); + QCOMPARE(store.contains(3), false); + + QCOMPARE(store.addCanceledResult(4), 4); + QCOMPARE(store.addCanceledResult(5), 5); + QCOMPARE(store.count(), 5); // 6 and 7 is renamed to 3 and 4 and becomes available + + QCOMPARE(store.contains(3), true); + QCOMPARE(store.contains(4), true); + + QCOMPARE(store.addResult(8, &int0), 8); + QCOMPARE(store.contains(5), true); + QCOMPARE(store.count(), 6); + + QCOMPARE(store.contains(6), false); + QCOMPARE(store.contains(7), false); + } +} + +void tst_QtConcurrentResultStore::addResults() +{ + + ResultStoreBase store; + store.addResults(-1, &vec0, 2, 2); + store.addResults(-1, &vec1, 2, 2); + ResultIteratorBase it = store.begin(); + QCOMPARE(it.resultIndex(), 0); + QVERIFY(it == store.begin()); + QVERIFY(it != store.end()); + + ++it; + QCOMPARE(it.resultIndex(), 1); + QVERIFY(it != store.begin()); + QVERIFY(it != store.end()); + + ++it; + QCOMPARE(it.resultIndex(), 2); + + ++it; + QCOMPARE(it.resultIndex(), 3); + + ++it; + QVERIFY(it == store.end()); +} + +void tst_QtConcurrentResultStore::resultIndex() +{ + ResultStore store; + store.addResult(-1, &int0); + store.addResults(-1, &vec0); + store.addResult(-1, &int1); + + ResultIteratorBase it = store.begin(); + QCOMPARE(it.resultIndex(), 0); + QVERIFY(it == store.begin()); + QVERIFY(it != store.end()); + + ++it; + QCOMPARE(it.resultIndex(), 1); + QVERIFY(it != store.begin()); + QVERIFY(it != store.end()); + + ++it; + QCOMPARE(it.resultIndex(), 2); + QVERIFY(it != store.end()); + ++it; + QCOMPARE(it.resultIndex(), 3); + QVERIFY(it != store.end()); + ++it; + QVERIFY(it == store.end()); + + QCOMPARE(store.resultAt(0).value(), int0); + QCOMPARE(store.resultAt(1).value(), vec0[0]); + QCOMPARE(store.resultAt(2).value(), vec0[1]); + QCOMPARE(store.resultAt(3).value(), int1); +} + +void tst_QtConcurrentResultStore::resultAt() +{ + { + ResultStore store; + store.addResult(-1, &int0); + store.addResults(-1, &vec0); + store.addResult(200, &int1); + + QCOMPARE(store.resultAt(0).value(), int0); + QCOMPARE(store.resultAt(1).value(), vec0[0]); + QCOMPARE(store.resultAt(2).value(), vec0[1]); + QCOMPARE(store.resultAt(200).value(), int1); + } + { + ResultStore store; + store.addResult(1, &int1); + store.addResult(0, &int0); + store.addResult(-1, &int2); + + QCOMPARE(store.resultAt(0).value(), int0); + QCOMPARE(store.resultAt(1).value(), int1); + QCOMPARE(store.resultAt(2).value(), int2); + } +} + +void tst_QtConcurrentResultStore::contains() +{ + { + ResultStore store; + QCOMPARE(store.contains(0), false); + QCOMPARE(store.contains(1), false); + QCOMPARE(store.contains(INT_MAX), false); + store.addResult(1, &int1); + QVERIFY(store.contains(int1)); + store.addResult(0, &int0); + QVERIFY(store.contains(int0)); + store.addResult(-1, &int2); + QVERIFY(store.contains(int2)); + } + { + ResultStore store; + store.addResult(1, &int0); + store.addResult(3, &int0); + store.addResults(6, &vec0); + QCOMPARE(store.contains(0), false); + QCOMPARE(store.contains(1), true); + QCOMPARE(store.contains(2), false); + QCOMPARE(store.contains(3), true); + QCOMPARE(store.contains(4), false); + QCOMPARE(store.contains(5), false); + QCOMPARE(store.contains(6), true); + QCOMPARE(store.contains(7), true); + } + + { + ResultStore store; + store.setFilterMode(true); + store.addResult(1, &int0); + store.addResult(3, &int0); + store.addResults(6, &vec0); + QCOMPARE(store.contains(0), false); + QCOMPARE(store.contains(1), false); + QCOMPARE(store.contains(2), false); + QCOMPARE(store.contains(3), false); + QCOMPARE(store.contains(4), false); + QCOMPARE(store.contains(5), false); + QCOMPARE(store.contains(6), false); + QCOMPARE(store.contains(7), false); + + store.addCanceledResult(0); + store.addCanceledResult(2); + store.addCanceledResults(4, 2); + + QCOMPARE(store.contains(0), true); + QCOMPARE(store.contains(1), true); + QCOMPARE(store.contains(2), true); + QCOMPARE(store.contains(3), true); + QCOMPARE(store.contains(4), false); + QCOMPARE(store.contains(5), false); + QCOMPARE(store.contains(6), false); + QCOMPARE(store.contains(7), false); + } + { + ResultStore store; + store.setFilterMode(true); + store.addCanceledResult(0); + QCOMPARE(store.contains(0), false); + + store.addResult(1, &int0); + QCOMPARE(store.contains(0), true); + QCOMPARE(store.contains(1), false); + } +} + +void tst_QtConcurrentResultStore::filterMode() +{ + // Test filter mode, where "gaps" in the result array aren't allowed. + ResultStore store; + QCOMPARE(store.filterMode(), false); + store.setFilterMode(true); + QVERIFY(store.filterMode()); + + store.addResult(0, &int0); + QCOMPARE(store.contains(0), true); + + store.addResult(2, &int2); // add result at index 2 + QCOMPARE(store.contains(2), false); // but 1 is missing, so this 2 won't be reported yet. + + store.addResult(1, &int1); + QCOMPARE(store.contains(1), true); + QCOMPARE(store.contains(2), true); // 2 should be visible now. + + store.addResult(4, &int0); + store.addResult(5, &int0); + store.addResult(7, &int0); + QCOMPARE(store.contains(4), false); + QCOMPARE(store.contains(5), false); + QCOMPARE(store.contains(7), false); + + store.addResult(3, &int0); // adding 3 makes 4 and 5 visible + QCOMPARE(store.contains(4), true); + QCOMPARE(store.contains(5), true); + QCOMPARE(store.contains(7), false); + + store.addResult(6, &int0); // adding 6 makes 7 visible + + QCOMPARE(store.contains(6), true); + QCOMPARE(store.contains(7), true); + QCOMPARE(store.contains(8), false); +} + +void tst_QtConcurrentResultStore::addCanceledResult() +{ + // test canceled results + ResultStore store; + store.setFilterMode(true); + + store.addResult(0, &int0); + QCOMPARE(store.contains(0), true); + + store.addResult(2, &int0); + QCOMPARE(store.contains(2), false); + + store.addCanceledResult(1); // report no result at 1 + + QCOMPARE(store.contains(0), true); + QCOMPARE(store.contains(1), true); // 2 gets renamed to 1 + QCOMPARE(store.contains(2), false); + + store.addResult(3, &int0); + QCOMPARE(store.contains(2), true); //3 gets renamed to 2 + + store.addResult(6, &int0); + store.addResult(7, &int0); + QCOMPARE(store.contains(3), false); + + store.addCanceledResult(4); + store.addCanceledResult(5); + + QCOMPARE(store.contains(3), true); //6 gets renamed to 3 + QCOMPARE(store.contains(4), true); //7 gets renamed to 4 + + store.addResult(8, &int0); + QCOMPARE(store.contains(5), true); //8 gets renamed to 4 + + QCOMPARE(store.contains(6), false); + QCOMPARE(store.contains(7), false); +} + +void tst_QtConcurrentResultStore::count() +{ + { + // test resultCount in non-filtered mode. It should always be possible + // to iterate through the results 0 to resultCount. + ResultStore store; + store.addResult(0, &int0); + + QCOMPARE(store.count(), 1); + + store.addResult(2, &int0); + + QCOMPARE(store.count(), 1); + + store.addResult(1, &int0); + QCOMPARE(store.count(), 3); + } + + { + ResultStore store; + store.addResult(2, &int0); + QCOMPARE(store.count(), 0); + + store.addResult(1, &int0); + QCOMPARE(store.count(), 0); + + store.addResult(0, &int0); + QCOMPARE(store.count(), 3); + } + + { + ResultStore store; + store.addResults(2, &vec1); + QCOMPARE(store.count(), 0); + + store.addResult(1, &int0); + QCOMPARE(store.count(), 0); + + store.addResult(0, &int0); + QCOMPARE(store.count(), 4); + } + + { + ResultStore store; + store.addResults(2, &vec1); + QCOMPARE(store.count(), 0); + + store.addResults(0, &vec0); + QCOMPARE(store.count(), 4); + } + { + ResultStore store; + store.addResults(3, &vec1); + QCOMPARE(store.count(), 0); + + store.addResults(0, &vec0); + QCOMPARE(store.count(), 2); + + store.addResult(2, &int0); + QCOMPARE(store.count(), 5); + } + + { + ResultStore store; + store.setFilterMode(true); + store.addResults(3, &vec1); + QCOMPARE(store.count(), 0); + + store.addResults(0, &vec0); + QCOMPARE(store.count(), 2); + + store.addCanceledResult(2); + QCOMPARE(store.count(), 4); + } + + { + ResultStore store; + store.setFilterMode(true); + store.addResults(3, &vec1); + QCOMPARE(store.count(), 0); + + store.addCanceledResults(0, 3); + QCOMPARE(store.count(), 2); + } + + { + ResultStore store; + store.setFilterMode(true); + store.addResults(3, &vec1); + QCOMPARE(store.count(), 0); + + store.addCanceledResults(0, 3); + QCOMPARE(store.count(), 2); // results at 3 and 4 become available at index 0, 1 + + store.addResult(5, &int0); + QCOMPARE(store.count(), 3);// result 5 becomes available at index 2 + } +} + +QTEST_MAIN(tst_QtConcurrentResultStore) +#include "tst_qresultstore.moc" diff --git a/tests/auto/corelib/thread/thread.pro b/tests/auto/corelib/thread/thread.pro index 12a284c7c7..8f063ee746 100644 --- a/tests/auto/corelib/thread/thread.pro +++ b/tests/auto/corelib/thread/thread.pro @@ -2,6 +2,7 @@ TEMPLATE=subdirs SUBDIRS=\ qatomicint \ qatomicpointer \ + qresultstore \ qmutex \ qmutexlocker \ qreadlocker \ -- cgit v1.2.3