1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtCore module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
42 #ifndef QTCONCURRENT_MAPKERNEL_H
43 #define QTCONCURRENT_MAPKERNEL_H
45 #include <QtConcurrent/qtconcurrent_global.h>
47 #ifndef QT_NO_CONCURRENT
49 #include <QtConcurrent/qtconcurrentiteratekernel.h>
50 #include <QtConcurrent/qtconcurrentreducekernel.h>
57 namespace QtConcurrent {
59 // map kernel, works with both parallel-for and parallel-while
60 template <typename Iterator, typename MapFunctor>
61 class MapKernel : public IterateKernel<Iterator, void>
65 typedef void ReturnType;
66 MapKernel(Iterator begin, Iterator end, MapFunctor _map)
67 : IterateKernel<Iterator, void>(begin, end), map(_map)
70 bool runIteration(Iterator it, int, void *)
76 bool runIterations(Iterator sequenceBeginIterator, int beginIndex, int endIndex, void *)
78 Iterator it = sequenceBeginIterator;
79 advance(it, beginIndex);
80 for (int i = beginIndex; i < endIndex; ++i) {
81 runIteration(it, i, 0);
89 template <typename ReducedResultType,
92 typename ReduceFunctor,
93 typename Reducer = ReduceKernel<ReduceFunctor,
95 typename MapFunctor::result_type> >
96 class MappedReducedKernel : public IterateKernel<Iterator, ReducedResultType>
98 ReducedResultType reducedResult;
100 ReduceFunctor reduce;
103 typedef ReducedResultType ReturnType;
104 MappedReducedKernel(Iterator begin, Iterator end, MapFunctor _map, ReduceFunctor _reduce, ReduceOptions reduceOptions)
105 : IterateKernel<Iterator, ReducedResultType>(begin, end), reducedResult(), map(_map), reduce(_reduce), reducer(reduceOptions)
108 MappedReducedKernel(ReducedResultType initialValue,
110 ReduceFunctor _reduce)
111 : reducedResult(initialValue), map(_map), reduce(_reduce)
114 bool runIteration(Iterator it, int index, ReducedResultType *)
116 IntermediateResults<typename MapFunctor::result_type> results;
117 results.begin = index;
118 results.end = index + 1;
120 results.vector.append(map(*it));
121 reducer.runReduce(reduce, reducedResult, results);
125 bool runIterations(Iterator sequenceBeginIterator, int begin, int end, ReducedResultType *)
127 IntermediateResults<typename MapFunctor::result_type> results;
128 results.begin = begin;
130 results.vector.reserve(end - begin);
132 Iterator it = sequenceBeginIterator;
134 for (int i = begin; i < end; ++i) {
135 results.vector.append(map(*(it)));
139 reducer.runReduce(reduce, reducedResult, results);
145 reducer.finish(reduce, reducedResult);
148 bool shouldThrottleThread()
150 return IterateKernel<Iterator, ReducedResultType>::shouldThrottleThread() || reducer.shouldThrottle();
153 bool shouldStartThread()
155 return IterateKernel<Iterator, ReducedResultType>::shouldStartThread() && reducer.shouldStartThread();
158 typedef ReducedResultType ResultType;
159 ReducedResultType *result()
161 return &reducedResult;
165 template <typename Iterator, typename MapFunctor>
166 class MappedEachKernel : public IterateKernel<Iterator, typename MapFunctor::result_type>
169 typedef typename MapFunctor::result_type T;
171 typedef T ReturnType;
172 typedef T ResultType;
174 MappedEachKernel(Iterator begin, Iterator end, MapFunctor _map)
175 : IterateKernel<Iterator, T>(begin, end), map(_map) { }
177 bool runIteration(Iterator it, int, T *result)
183 bool runIterations(Iterator sequenceBeginIterator, int begin, int end, T *results)
186 Iterator it = sequenceBeginIterator;
188 for (int i = begin; i < end; ++i) {
189 runIteration(it, i, results + (i - begin));
197 template <typename Iterator, typename Functor>
198 inline ThreadEngineStarter<void> startMap(Iterator begin, Iterator end, Functor functor)
200 return startThreadEngine(new MapKernel<Iterator, Functor>(begin, end, functor));
203 template <typename T, typename Iterator, typename Functor>
204 inline ThreadEngineStarter<T> startMapped(Iterator begin, Iterator end, Functor functor)
206 return startThreadEngine(new MappedEachKernel<Iterator, Functor>(begin, end, functor));
210 The SequnceHolder class is used to hold a reference to the
211 sequence we are working on.
213 template <typename Sequence, typename Base, typename Functor>
214 struct SequenceHolder1 : public Base
216 SequenceHolder1(const Sequence &_sequence, Functor functor)
217 : Base(_sequence.begin(), _sequence.end(), functor), sequence(_sequence)
225 // Clear the sequence to make sure all temporaries are destroyed
226 // before finished is signaled.
227 sequence = Sequence();
231 template <typename T, typename Sequence, typename Functor>
232 inline ThreadEngineStarter<T> startMapped(const Sequence &sequence, Functor functor)
234 typedef SequenceHolder1<Sequence,
235 MappedEachKernel<typename Sequence::const_iterator , Functor>, Functor>
238 return startThreadEngine(new SequenceHolderType(sequence, functor));
241 template <typename IntermediateType, typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor>
242 inline ThreadEngineStarter<ResultType> startMappedReduced(const Sequence & sequence,
243 MapFunctor mapFunctor, ReduceFunctor reduceFunctor,
244 ReduceOptions options)
246 typedef typename Sequence::const_iterator Iterator;
247 typedef ReduceKernel<ReduceFunctor, ResultType, IntermediateType> Reducer;
248 typedef MappedReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer> MappedReduceType;
249 typedef SequenceHolder2<Sequence, MappedReduceType, MapFunctor, ReduceFunctor> SequenceHolderType;
250 return startThreadEngine(new SequenceHolderType(sequence, mapFunctor, reduceFunctor, options));
253 template <typename IntermediateType, typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
254 inline ThreadEngineStarter<ResultType> startMappedReduced(Iterator begin, Iterator end,
255 MapFunctor mapFunctor, ReduceFunctor reduceFunctor,
256 ReduceOptions options)
258 typedef ReduceKernel<ReduceFunctor, ResultType, IntermediateType> Reducer;
259 typedef MappedReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer> MappedReduceType;
260 return startThreadEngine(new MappedReduceType(begin, end, mapFunctor, reduceFunctor, options));
263 } // namespace QtConcurrent
270 #endif // QT_NO_CONCURRENT