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
42#ifndef QTCONCURRENT_RESULTSTORE_H
43#define QTCONCURRENT_RESULTSTORE_H
44
45#include <QtCore/qglobal.h>
46
47#ifndef QT_NO_QFUTURE
48
49#include <QtCore/qmap.h>
50#include <QtCore/qdebug.h>
51
52QT_BEGIN_HEADER
53QT_BEGIN_NAMESPACE
54
55QT_MODULE(Core)
56
57/*
58 ResultStore stores indexed results. Results can be added and retrieved
59 either individually batched in a QVector. Retriveing results and checking
60 which indexes are in the store can be done either by iterating or by random
61 accees. In addition results kan be removed from the front of the store,
62 either individually or in batches.
63*/
64
65#ifndef qdoc
66
67namespace QtConcurrent {
68
69class ResultItem
70{
71public:
72 ResultItem(const void *_result, int _count) : m_count(_count), result(_result) { } // contruct with vector of results
73 ResultItem(const void *_result) : m_count(0), result(_result) { } // construct with result
74 ResultItem() : m_count(0), result(0) { }
75 bool isValid() const { return result != 0; }
76 bool isVector() const { return m_count != 0; }
77 int count() const { return (m_count == 0) ? 1 : m_count; }
78 int m_count; // result is either a pointer to a result or to a vector of results,
79 const void *result; // if count is 0 it's a result, otherwise it's a vector.
80};
81
82class Q_CORE_EXPORT ResultIteratorBase
83{
84public:
85 ResultIteratorBase();
86 ResultIteratorBase(QMap<int, ResultItem>::const_iterator _mapIterator, int _vectorIndex = 0);
87 int vectorIndex() const;
88 int resultIndex() const;
89
90 ResultIteratorBase operator++();
91 int batchSize() const;
92 void batchedAdvance();
93 bool operator==(const ResultIteratorBase &other) const;
94 bool operator!=(const ResultIteratorBase &other) const;
95 bool isVector() const;
96 bool canIncrementVectorIndex() const;
97protected:
98 QMap<int, ResultItem>::const_iterator mapIterator;
99 int m_vectorIndex;
100};
101
102template <typename T>
103class ResultIterator : public ResultIteratorBase
104{
105public:
106 ResultIterator(const ResultIteratorBase &base)
107 : ResultIteratorBase(base) { }
108
109 const T &value() const
110 {
111 return *pointer();
112 }
113
114 const T *pointer() const
115 {
116 if (mapIterator.value().isVector())
117 return &(reinterpret_cast<const QVector<T> *>(mapIterator.value().result)->at(m_vectorIndex));
118 else
119 return reinterpret_cast<const T *>(mapIterator.value().result);
120 }
121};
122
123class Q_CORE_EXPORT ResultStoreBase
124{
125public:
126 ResultStoreBase();
127 void setFilterMode(bool enable);
128 bool filterMode() const;
129 int addResult(int index, const void *result);
130 int addResults(int index, const void *results, int vectorSize, int logicalCount);
131 ResultIteratorBase begin() const;
132 ResultIteratorBase end() const;
133 bool hasNextResult() const;
134 ResultIteratorBase resultAt(int index) const;
135 bool contains(int index) const;
136 int count() const;
137 virtual ~ResultStoreBase() { };
138
139protected:
140 int insertResultItem(int index, ResultItem &resultItem);
141 void insertResultItemIfValid(int index, ResultItem &resultItem);
142 void syncPendingResults();
143 void syncResultCount();
144 int updateInsertIndex(int index, int _count);
145
146 QMap<int, ResultItem> m_results;
147 int insertIndex; // The index where the next results(s) will be inserted.
148 int resultCount; // The number of consecutive results stored, starting at index 0.
149
150 bool m_filterMode;
151 QMap<int, ResultItem> pendingResults;
152 int filteredResults;
153
154};
155
156template <typename T>
157class ResultStore : public ResultStoreBase
158{
159public:
160 ResultStore() { }
161
162 ResultStore(const ResultStoreBase &base)
163 : ResultStoreBase(base) { }
164
165 int addResult(int index, const T *result)
166 {
167 if (result == 0)
168 return ResultStoreBase::addResult(index, result);
169 else
170 return ResultStoreBase::addResult(index, new T(*result));
171 }
172
173 int addResults(int index, const QVector<T> *results)
174 {
175 return ResultStoreBase::addResults(index, new QVector<T>(*results), results->count(), results->count());
176 }
177
178 int addResults(int index, const QVector<T> *results, int totalCount)
179 {
180 if (m_filterMode && totalCount && !results->count())
181 return ResultStoreBase::addResults(index, 0, 0, totalCount);
182 else
183 return ResultStoreBase::addResults(index, new QVector<T>(*results), results->count(), totalCount);
184 }
185
186 int addCanceledResult(int index)
187 {
188 return addResult(index, 0);
189 }
190
191 int addCanceledResults(int index, int _count)
192 {
193 QVector<T> empty;
194 return addResults(index, &empty, _count);
195 }
196
197 ResultIterator<T> begin() const
198 {
199 return static_cast<ResultIterator<T> >(ResultStoreBase::begin());
200 }
201
202 ResultIterator<T> end() const
203 {
204 return static_cast<ResultIterator<T> >(ResultStoreBase::end());
205 }
206
207 ResultIterator<T> resultAt(int index) const
208 {
209 return static_cast<ResultIterator<T> >(ResultStoreBase::resultAt(index));
210 }
211
212 void clear()
213 {
214 QMap<int, ResultItem>::const_iterator mapIterator = m_results.constBegin();
215 while (mapIterator != m_results.constEnd()) {
216 if (mapIterator.value().isVector())
217 delete reinterpret_cast<const QVector<T> *>(mapIterator.value().result);
218 else
219 delete reinterpret_cast<const T *>(mapIterator.value().result);
220 ++mapIterator;
221 }
222 resultCount = 0;
223 m_results.clear();
224 }
225
226 ~ResultStore()
227 {
228 clear();
229 }
230
231};
232
233} // namespace QtConcurrent
234
235#endif //qdoc
236
237QT_END_NAMESPACE
238QT_END_HEADER
239
240#endif // QT_NO_CONCURRENT
241
242#endif
243