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 | |
52 | QT_BEGIN_HEADER |
53 | QT_BEGIN_NAMESPACE |
54 | |
55 | QT_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 | |
67 | namespace QtConcurrent { |
68 | |
69 | class ResultItem |
70 | { |
71 | public: |
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 | |
82 | class Q_CORE_EXPORT ResultIteratorBase |
83 | { |
84 | public: |
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; |
97 | protected: |
98 | QMap<int, ResultItem>::const_iterator mapIterator; |
99 | int m_vectorIndex; |
100 | }; |
101 | |
102 | template <typename T> |
103 | class ResultIterator : public ResultIteratorBase |
104 | { |
105 | public: |
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 | |
123 | class Q_CORE_EXPORT ResultStoreBase |
124 | { |
125 | public: |
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 | |
139 | protected: |
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 | |
156 | template <typename T> |
157 | class ResultStore : public ResultStoreBase |
158 | { |
159 | public: |
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 | |
237 | QT_END_NAMESPACE |
238 | QT_END_HEADER |
239 | |
240 | #endif // QT_NO_CONCURRENT |
241 | |
242 | #endif |
243 | |