blob: 55f717d39c48aa5274952818aa1aa0f59dbd4e58 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qtconcurrentresultstore.h"
#ifndef QT_NO_QFUTURE
QT_BEGIN_NAMESPACE
namespace QtConcurrent {
ResultIteratorBase::ResultIteratorBase()
: mapIterator(QMap<int, ResultItem>::const_iterator()), m_vectorIndex(0) { }
ResultIteratorBase::ResultIteratorBase(QMap<int, ResultItem>::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<int, ResultItem>::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<int, ResultItem>::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