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_FILTERKERNEL_H |
43 | #define QTCONCURRENT_FILTERKERNEL_H |
44 | |
45 | #include <QtCore/qglobal.h> |
46 | |
47 | #ifndef QT_NO_CONCURRENT |
48 | |
49 | #include <QtCore/qtconcurrentiteratekernel.h> |
50 | #include <QtCore/qtconcurrentmapkernel.h> |
51 | #include <QtCore/qtconcurrentreducekernel.h> |
52 | |
53 | QT_BEGIN_HEADER |
54 | QT_BEGIN_NAMESPACE |
55 | |
56 | QT_MODULE(Core) |
57 | |
58 | #ifndef qdoc |
59 | |
60 | namespace QtConcurrent { |
61 | |
62 | template <typename T> |
63 | struct qValueType |
64 | { |
65 | typedef typename T::value_type value_type; |
66 | }; |
67 | |
68 | template <typename T> |
69 | struct qValueType<const T*> |
70 | { |
71 | typedef T value_type; |
72 | }; |
73 | |
74 | template <typename T> |
75 | struct qValueType<T*> |
76 | { |
77 | typedef T value_type; |
78 | }; |
79 | |
80 | // Implementation of filter |
81 | template <typename Sequence, typename KeepFunctor, typename ReduceFunctor> |
82 | class FilterKernel : public IterateKernel<typename Sequence::const_iterator, void> |
83 | { |
84 | typedef ReduceKernel<ReduceFunctor, Sequence, typename Sequence::value_type> Reducer; |
85 | typedef IterateKernel<typename Sequence::const_iterator, void> IterateKernelType; |
86 | typedef typename ReduceFunctor::result_type T; |
87 | |
88 | Sequence reducedResult; |
89 | Sequence &sequence; |
90 | KeepFunctor keep; |
91 | ReduceFunctor reduce; |
92 | Reducer reducer; |
93 | |
94 | public: |
95 | FilterKernel(Sequence &_sequence, KeepFunctor _keep, ReduceFunctor _reduce) |
96 | : IterateKernelType(const_cast<const Sequence &>(_sequence).begin(), const_cast<const Sequence &>(_sequence).end()), reducedResult(), |
97 | sequence(_sequence), |
98 | keep(_keep), |
99 | reduce(_reduce), |
100 | reducer(OrderedReduce) |
101 | { } |
102 | |
103 | bool runIteration(typename Sequence::const_iterator it, int index, T *) |
104 | { |
105 | IntermediateResults<typename Sequence::value_type> results; |
106 | results.begin = index; |
107 | results.end = index + 1; |
108 | |
109 | if (keep(*it)) |
110 | results.vector.append(*it); |
111 | |
112 | reducer.runReduce(reduce, reducedResult, results); |
113 | return false; |
114 | } |
115 | |
116 | bool runIterations(typename Sequence::const_iterator sequenceBeginIterator, int begin, int end, T *) |
117 | { |
118 | IntermediateResults<typename Sequence::value_type> results; |
119 | results.begin = begin; |
120 | results.end = end; |
121 | results.vector.reserve(end - begin); |
122 | |
123 | |
124 | typename Sequence::const_iterator it = sequenceBeginIterator; |
125 | advance(it, begin); |
126 | for (int i = begin; i < end; ++i) { |
127 | if (keep(*it)) |
128 | results.vector.append(*it); |
129 | advance(it, 1); |
130 | } |
131 | |
132 | reducer.runReduce(reduce, reducedResult, results); |
133 | return false; |
134 | } |
135 | |
136 | void finish() |
137 | { |
138 | reducer.finish(reduce, reducedResult); |
139 | sequence = reducedResult; |
140 | } |
141 | |
142 | inline bool shouldThrottleThread() |
143 | { |
144 | return IterateKernelType::shouldThrottleThread() || reducer.shouldThrottle(); |
145 | } |
146 | |
147 | inline bool shouldStartThread() |
148 | { |
149 | return IterateKernelType::shouldStartThread() && reducer.shouldStartThread(); |
150 | } |
151 | |
152 | typedef void ReturnType; |
153 | typedef void ResultType; |
154 | }; |
155 | |
156 | // Implementation of filter-reduce |
157 | template <typename ReducedResultType, |
158 | typename Iterator, |
159 | typename KeepFunctor, |
160 | typename ReduceFunctor, |
161 | typename Reducer = ReduceKernel<ReduceFunctor, |
162 | ReducedResultType, |
163 | typename qValueType<Iterator>::value_type> > |
164 | class FilteredReducedKernel : public IterateKernel<Iterator, ReducedResultType> |
165 | { |
166 | ReducedResultType reducedResult; |
167 | KeepFunctor keep; |
168 | ReduceFunctor reduce; |
169 | Reducer reducer; |
170 | typedef IterateKernel<Iterator, ReducedResultType> IterateKernelType; |
171 | |
172 | public: |
173 | FilteredReducedKernel(Iterator begin, |
174 | Iterator end, |
175 | KeepFunctor _keep, |
176 | ReduceFunctor _reduce, |
177 | ReduceOptions reduceOption) |
178 | : IterateKernelType(begin, end), reducedResult(), keep(_keep), reduce(_reduce), reducer(reduceOption) |
179 | { } |
180 | |
181 | #if 0 |
182 | FilteredReducedKernel(ReducedResultType initialValue, |
183 | KeepFunctor keep, |
184 | ReduceFunctor reduce, |
185 | ReduceOption reduceOption) |
186 | : reducedResult(initialValue), keep(keep), reduce(reduce), reducer(reduceOption) |
187 | { } |
188 | #endif |
189 | |
190 | bool runIteration(Iterator it, int index, ReducedResultType *) |
191 | { |
192 | IntermediateResults<typename qValueType<Iterator>::value_type> results; |
193 | results.begin = index; |
194 | results.end = index + 1; |
195 | |
196 | if (keep(*it)) |
197 | results.vector.append(*it); |
198 | |
199 | reducer.runReduce(reduce, reducedResult, results); |
200 | return false; |
201 | } |
202 | |
203 | bool runIterations(Iterator sequenceBeginIterator, int begin, int end, ReducedResultType *) |
204 | { |
205 | IntermediateResults<typename qValueType<Iterator>::value_type> results; |
206 | results.begin = begin; |
207 | results.end = end; |
208 | results.vector.reserve(end - begin); |
209 | |
210 | Iterator it = sequenceBeginIterator; |
211 | advance(it, begin); |
212 | for (int i = begin; i < end; ++i) { |
213 | if (keep(*it)) |
214 | results.vector.append(*it); |
215 | advance(it, 1); |
216 | } |
217 | |
218 | reducer.runReduce(reduce, reducedResult, results); |
219 | return false; |
220 | } |
221 | |
222 | void finish() |
223 | { |
224 | reducer.finish(reduce, reducedResult); |
225 | } |
226 | |
227 | inline bool shouldThrottleThread() |
228 | { |
229 | return IterateKernelType::shouldThrottleThread() || reducer.shouldThrottle(); |
230 | } |
231 | |
232 | inline bool shouldStartThread() |
233 | { |
234 | return IterateKernelType::shouldStartThread() && reducer.shouldStartThread(); |
235 | } |
236 | |
237 | typedef ReducedResultType ReturnType; |
238 | typedef ReducedResultType ResultType; |
239 | ReducedResultType *result() |
240 | { |
241 | return &reducedResult; |
242 | } |
243 | }; |
244 | |
245 | // Implementation of filter that reports individual results via QFutureInterface |
246 | template <typename Iterator, typename KeepFunctor> |
247 | class FilteredEachKernel : public IterateKernel<Iterator, typename qValueType<Iterator>::value_type> |
248 | { |
249 | typedef typename qValueType<Iterator>::value_type T; |
250 | typedef IterateKernel<Iterator, T> IterateKernelType; |
251 | |
252 | KeepFunctor keep; |
253 | |
254 | public: |
255 | typedef T ReturnType; |
256 | typedef T ResultType; |
257 | |
258 | FilteredEachKernel(Iterator begin, Iterator end, KeepFunctor _keep) |
259 | : IterateKernelType(begin, end), keep(_keep) |
260 | { } |
261 | |
262 | void start() |
263 | { |
264 | if (this->futureInterface) |
265 | this->futureInterface->setFilterMode(true); |
266 | IterateKernelType::start(); |
267 | } |
268 | |
269 | bool runIteration(Iterator it, int index, T *) |
270 | { |
271 | if (keep(*it)) |
272 | this->reportResult(&(*it), index); |
273 | else |
274 | this->reportResult(0, index); |
275 | return false; |
276 | } |
277 | |
278 | bool runIterations(Iterator sequenceBeginIterator, int begin, int end, T *) |
279 | { |
280 | const int count = end - begin; |
281 | IntermediateResults<typename qValueType<Iterator>::value_type> results; |
282 | results.begin = begin; |
283 | results.end = end; |
284 | results.vector.reserve(count); |
285 | |
286 | Iterator it = sequenceBeginIterator; |
287 | advance(it, begin); |
288 | for (int i = begin; i < end; ++i) { |
289 | if (keep(*it)) |
290 | results.vector.append(*it); |
291 | advance(it, 1); |
292 | } |
293 | |
294 | this->reportResults(results.vector, begin, count); |
295 | return false; |
296 | } |
297 | }; |
298 | |
299 | template <typename Iterator, typename KeepFunctor> |
300 | inline |
301 | ThreadEngineStarter<typename qValueType<Iterator>::value_type> |
302 | startFiltered(Iterator begin, Iterator end, KeepFunctor functor) |
303 | { |
304 | return startThreadEngine(new FilteredEachKernel<Iterator, KeepFunctor>(begin, end, functor)); |
305 | } |
306 | |
307 | template <typename Sequence, typename KeepFunctor> |
308 | inline ThreadEngineStarter<typename Sequence::value_type> |
309 | startFiltered(const Sequence &sequence, KeepFunctor functor) |
310 | { |
311 | typedef SequenceHolder1<Sequence, |
312 | FilteredEachKernel<typename Sequence::const_iterator, KeepFunctor>, |
313 | KeepFunctor> |
314 | SequenceHolderType; |
315 | return startThreadEngine(new SequenceHolderType(sequence, functor)); |
316 | } |
317 | |
318 | template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor> |
319 | inline ThreadEngineStarter<ResultType> startFilteredReduced(const Sequence & sequence, |
320 | MapFunctor mapFunctor, ReduceFunctor reduceFunctor, |
321 | ReduceOptions options) |
322 | { |
323 | typedef typename Sequence::const_iterator Iterator; |
324 | typedef ReduceKernel<ReduceFunctor, ResultType, typename qValueType<Iterator>::value_type > Reducer; |
325 | typedef FilteredReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer> FilteredReduceType; |
326 | typedef SequenceHolder2<Sequence, FilteredReduceType, MapFunctor, ReduceFunctor> SequenceHolderType; |
327 | return startThreadEngine(new SequenceHolderType(sequence, mapFunctor, reduceFunctor, options)); |
328 | } |
329 | |
330 | |
331 | template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor> |
332 | inline ThreadEngineStarter<ResultType> startFilteredReduced(Iterator begin, Iterator end, |
333 | MapFunctor mapFunctor, ReduceFunctor reduceFunctor, |
334 | ReduceOptions options) |
335 | { |
336 | typedef ReduceKernel<ReduceFunctor, ResultType, typename qValueType<Iterator>::value_type> Reducer; |
337 | typedef FilteredReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer> FilteredReduceType; |
338 | return startThreadEngine(new FilteredReduceType(begin, end, mapFunctor, reduceFunctor, options)); |
339 | } |
340 | |
341 | |
342 | } // namespace QtConcurrent |
343 | |
344 | #endif // qdoc |
345 | |
346 | QT_END_NAMESPACE |
347 | QT_END_HEADER |
348 | |
349 | #endif // QT_NO_CONCURRENT |
350 | |
351 | #endif |
352 | |