Qt 4.8
qtconcurrentresultstore.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
43 
44 #ifndef QT_NO_QFUTURE
45 
47 
48 namespace QtConcurrent {
49 
50 ResultIteratorBase::ResultIteratorBase()
51  : mapIterator(QMap<int, ResultItem>::const_iterator()), m_vectorIndex(0) { }
52 ResultIteratorBase::ResultIteratorBase(QMap<int, ResultItem>::const_iterator _mapIterator, int _vectorIndex)
53  : mapIterator(_mapIterator), m_vectorIndex(_vectorIndex) { }
54 
55 int ResultIteratorBase::vectorIndex() const { return m_vectorIndex; }
56 int ResultIteratorBase::resultIndex() const { return mapIterator.key() + m_vectorIndex; }
57 
58 ResultIteratorBase ResultIteratorBase::operator++()
59 {
60  if (canIncrementVectorIndex()) {
61  ++m_vectorIndex;
62  } else {
63  ++mapIterator;
64  m_vectorIndex = 0;
65  }
66  return *this;
67 }
68 
69 int ResultIteratorBase::batchSize() const
70 {
71  return mapIterator.value().count();
72 }
73 
74 void ResultIteratorBase::batchedAdvance()
75 {
76  ++mapIterator;
77  m_vectorIndex = 0;
78 }
79 
80 bool ResultIteratorBase::operator==(const ResultIteratorBase &other) const
81 {
82  return (mapIterator == other.mapIterator && m_vectorIndex == other.m_vectorIndex);
83 }
84 
85 bool ResultIteratorBase::operator!=(const ResultIteratorBase &other) const
86 {
87  return !operator==(other);
88 }
89 
90 bool ResultIteratorBase::isVector() const
91 {
92  return mapIterator.value().isVector();
93 }
94 
95 bool ResultIteratorBase::canIncrementVectorIndex() const
96 {
97  return (m_vectorIndex + 1 < mapIterator.value().m_count);
98 }
99 
100 ResultStoreBase::ResultStoreBase()
101  : insertIndex(0), resultCount(0), m_filterMode(false), filteredResults(0) { }
102 
103 void ResultStoreBase::setFilterMode(bool enable)
104 {
105  m_filterMode = enable;
106 }
107 
108 bool ResultStoreBase::filterMode() const
109 {
110  return m_filterMode;
111 }
112 
113 void ResultStoreBase::syncResultCount()
114 {
115  ResultIteratorBase it = resultAt(resultCount);
116  while (it != end()) {
117  resultCount += it.batchSize();
118  it = resultAt(resultCount);
119  }
120 }
121 
122 void ResultStoreBase::insertResultItemIfValid(int index, ResultItem &resultItem)
123 {
124  if (resultItem.isValid()) {
125  m_results[index] = resultItem;
126  syncResultCount();
127  } else {
128  filteredResults += resultItem.count();
129  }
130 }
131 
132 int ResultStoreBase::insertResultItem(int index, ResultItem &resultItem)
133 {
134  int storeIndex;
135  if (m_filterMode && index != -1 && index > insertIndex) {
136  pendingResults[index] = resultItem;
137  storeIndex = index;
138  } else {
139  storeIndex = updateInsertIndex(index, resultItem.count());
140  insertResultItemIfValid(storeIndex - filteredResults, resultItem);
141  }
142  syncPendingResults();
143  return storeIndex;
144 }
145 
146 void ResultStoreBase::syncPendingResults()
147 {
148  // check if we can insert any of the pending results:
149  QMap<int, ResultItem>::iterator it = pendingResults.begin();
150  while (it != pendingResults.end()) {
151  int index = it.key();
152  if (index != resultCount + filteredResults)
153  break;
154 
155  ResultItem result = it.value();
156  insertResultItemIfValid(index - filteredResults, result);
157  pendingResults.erase(it);
158  it = pendingResults.begin();
159  }
160 }
161 
162 int ResultStoreBase::addResult(int index, const void *result)
163 {
164  ResultItem resultItem(result, 0); // 0 means "not a vector"
165  return insertResultItem(index, resultItem);
166 }
167 
168 int ResultStoreBase::addResults(int index, const void *results, int vectorSize, int totalCount)
169 {
170  if (m_filterMode == false || vectorSize == totalCount) {
171  ResultItem resultItem(results, vectorSize);
172  return insertResultItem(index, resultItem);
173  } else {
174  if (vectorSize > 0) {
175  ResultItem filteredIn(results, vectorSize);
176  insertResultItem(index, filteredIn);
177  }
178  ResultItem filteredAway(0, totalCount - vectorSize);
179  return insertResultItem(index + vectorSize, filteredAway);
180  }
181 }
182 
183 ResultIteratorBase ResultStoreBase::begin() const
184 {
185  return ResultIteratorBase(m_results.begin());
186 }
187 
188 ResultIteratorBase ResultStoreBase::end() const
189 {
190  return ResultIteratorBase(m_results.end());
191 }
192 
193 bool ResultStoreBase::hasNextResult() const
194 {
195  return begin() != end();
196 }
197 
198 ResultIteratorBase ResultStoreBase::resultAt(int index) const
199 {
200  if (m_results.isEmpty())
201  return ResultIteratorBase(m_results.end());
202  QMap<int, ResultItem>::const_iterator it = m_results.lowerBound(index);
203 
204  // lowerBound returns either an iterator to the result or an iterator
205  // to the nearest greater index. If the latter happens it might be
206  // that the result is stored in a vector at the previous index.
207  if (it == m_results.end()) {
208  --it;
209  if (it.value().isVector() == false) {
210  return ResultIteratorBase(m_results.end());
211  }
212  } else {
213  if (it.key() > index) {
214  if (it == m_results.begin())
215  return ResultIteratorBase(m_results.end());
216  --it;
217  }
218  }
219 
220  const int vectorIndex = index - it.key();
221 
222  if (vectorIndex >= it.value().count())
223  return ResultIteratorBase(m_results.end());
224  else if (it.value().isVector() == false && vectorIndex != 0)
225  return ResultIteratorBase(m_results.end());
226  return ResultIteratorBase(it, vectorIndex);
227 }
228 
229 bool ResultStoreBase::contains(int index) const
230 {
231  return (resultAt(index) != end());
232 }
233 
234 int ResultStoreBase::count() const
235 {
236  return resultCount;
237 }
238 
239 // returns the insert index, calling this function with
240 // index equal to -1 returns the next available index.
241 int ResultStoreBase::updateInsertIndex(int index, int _count)
242 {
243  if (index == -1) {
244  index = insertIndex;
245  insertIndex += _count;
246  } else {
247  insertIndex = qMax(index + _count, insertIndex);
248  }
249  return index;
250 }
251 
252 } // namespace QtConcurrent
253 
255 
256 #endif // QT_NO_CONCURRENT
const Key & key() const
Returns the current item&#39;s key as a const reference.
Definition: qmap.h:250
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
#define it(className, varName)
const Key & key() const
Returns the current item&#39;s key.
Definition: qmap.h:324
bool operator!=(QBool b1, bool b2)
Definition: qglobal.h:2026
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
T & value() const
Returns a modifiable reference to the current item&#39;s value.
Definition: qmap.h:251
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
The QMap::const_iterator class provides an STL-style const iterator for QMap and QMultiMap.
Definition: qmap.h:301
The QMap::iterator class provides an STL-style non-const iterator for QMap and QMultiMap.
Definition: qmap.h:233
The QtConcurrent namespace provides high-level APIs that make it possible to write multi-threaded pro...
const T & value() const
Returns the current item&#39;s value.
Definition: qmap.h:325
quint16 index
static const KeyPair *const end
bool operator==(QBool b1, bool b2)
Definition: qglobal.h:2023
The QMap class is a template class that provides a skip-list-based dictionary.
Definition: qdatastream.h:67