Partially revert e84e86dc.
[profile/ivi/qtbase.git] / src / concurrent / qtconcurrentmapkernel.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 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_MAPKERNEL_H
43 #define QTCONCURRENT_MAPKERNEL_H
44
45 #include <QtConcurrent/qtconcurrent_global.h>
46
47 #ifndef QT_NO_CONCURRENT
48
49 #include <QtConcurrent/qtconcurrentiteratekernel.h>
50 #include <QtConcurrent/qtconcurrentreducekernel.h>
51
52 QT_BEGIN_HEADER
53 QT_BEGIN_NAMESPACE
54
55
56 #ifndef qdoc
57 namespace QtConcurrent {
58
59 // map kernel, works with both parallel-for and parallel-while
60 template <typename Iterator, typename MapFunctor>
61 class MapKernel : public IterateKernel<Iterator, void>
62 {
63     MapFunctor map;
64 public:
65     typedef void ReturnType;
66     MapKernel(Iterator begin, Iterator end, MapFunctor _map)
67         : IterateKernel<Iterator, void>(begin, end), map(_map)
68     { }
69
70     bool runIteration(Iterator it, int, void *)
71     {
72         map(*it);
73         return false;
74     }
75
76     bool runIterations(Iterator sequenceBeginIterator, int beginIndex, int endIndex, void *)
77     {
78         Iterator it = sequenceBeginIterator;
79         advance(it, beginIndex);
80         for (int i = beginIndex; i < endIndex; ++i) {
81             runIteration(it, i, 0);
82             advance(it, 1);
83         }
84        
85         return false;
86     }
87 };
88
89 template <typename ReducedResultType,
90           typename Iterator,
91           typename MapFunctor,
92           typename ReduceFunctor,
93           typename Reducer = ReduceKernel<ReduceFunctor,
94                                           ReducedResultType,
95                                           typename MapFunctor::result_type> >
96 class MappedReducedKernel : public IterateKernel<Iterator, ReducedResultType>
97 {
98     ReducedResultType reducedResult;
99     MapFunctor map;
100     ReduceFunctor reduce;
101     Reducer reducer;
102 public:
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)
106     { }
107
108     MappedReducedKernel(ReducedResultType initialValue,
109                      MapFunctor _map,
110                      ReduceFunctor _reduce)
111         : reducedResult(initialValue), map(_map), reduce(_reduce)
112     { }
113
114     bool runIteration(Iterator it, int index, ReducedResultType *)
115     {
116         IntermediateResults<typename MapFunctor::result_type> results;
117         results.begin = index;
118         results.end = index + 1;
119
120         results.vector.append(map(*it));
121         reducer.runReduce(reduce, reducedResult, results);
122         return false;
123     }
124
125     bool runIterations(Iterator sequenceBeginIterator, int begin, int end, ReducedResultType *)
126     {
127         IntermediateResults<typename MapFunctor::result_type> results;
128         results.begin = begin;
129         results.end = end;
130         results.vector.reserve(end - begin);
131
132         Iterator it = sequenceBeginIterator;
133         advance(it, begin);
134         for (int i = begin; i < end; ++i) {
135             results.vector.append(map(*(it)));
136             advance(it, 1);
137         }
138
139         reducer.runReduce(reduce, reducedResult, results);
140         return false;
141     }
142
143     void finish()
144     {
145         reducer.finish(reduce, reducedResult);
146     }
147
148     bool shouldThrottleThread()
149     {
150         return IterateKernel<Iterator, ReducedResultType>::shouldThrottleThread() || reducer.shouldThrottle();
151     }
152
153     bool shouldStartThread()
154     {
155         return IterateKernel<Iterator, ReducedResultType>::shouldStartThread() && reducer.shouldStartThread();
156     }
157
158     typedef ReducedResultType ResultType;
159     ReducedResultType *result()
160     {
161         return &reducedResult;
162     }
163 };
164
165 template <typename Iterator, typename MapFunctor>
166 class MappedEachKernel : public IterateKernel<Iterator, typename MapFunctor::result_type>
167 {
168     MapFunctor map;
169     typedef typename MapFunctor::result_type T;
170 public:
171     typedef T ReturnType;
172     typedef T ResultType;
173
174     MappedEachKernel(Iterator begin, Iterator end, MapFunctor _map)
175         : IterateKernel<Iterator, T>(begin, end), map(_map) { }
176
177     bool runIteration(Iterator it, int,  T *result)
178     {
179         *result = map(*it);
180         return true;
181     }
182
183     bool runIterations(Iterator sequenceBeginIterator, int begin, int end, T *results)
184     {
185
186         Iterator it = sequenceBeginIterator;
187         advance(it, begin);
188         for (int i = begin; i < end; ++i) {
189             runIteration(it, i, results + (i - begin));
190             advance(it, 1);
191         }
192
193         return true;
194     }
195 };
196
197 template <typename Iterator, typename Functor>
198 inline ThreadEngineStarter<void> startMap(Iterator begin, Iterator end, Functor functor)
199 {
200     return startThreadEngine(new MapKernel<Iterator, Functor>(begin, end, functor));
201 }
202
203 template <typename T, typename Iterator, typename Functor>
204 inline ThreadEngineStarter<T> startMapped(Iterator begin, Iterator end, Functor functor)
205 {
206     return startThreadEngine(new MappedEachKernel<Iterator, Functor>(begin, end, functor));
207 }
208
209 /*
210     The SequnceHolder class is used to hold a reference to the
211     sequence we are working on.
212 */
213 template <typename Sequence, typename Base, typename Functor>
214 struct SequenceHolder1 : public Base
215 {
216     SequenceHolder1(const Sequence &_sequence, Functor functor)
217         : Base(_sequence.begin(), _sequence.end(), functor), sequence(_sequence)
218     { }
219
220     Sequence sequence;
221
222     void finish()
223     {
224         Base::finish();
225         // Clear the sequence to make sure all temporaries are destroyed
226         // before finished is signaled.
227         sequence = Sequence();
228     }
229 };
230
231 template <typename T, typename Sequence, typename Functor>
232 inline ThreadEngineStarter<T> startMapped(const Sequence &sequence, Functor functor)
233 {
234     typedef SequenceHolder1<Sequence,
235                             MappedEachKernel<typename Sequence::const_iterator , Functor>, Functor>
236                             SequenceHolderType;
237
238     return startThreadEngine(new SequenceHolderType(sequence, functor));
239 }
240
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)
245 {
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));
251 }
252
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)
257 {
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));
261 }
262
263 } // namespace QtConcurrent
264
265 #endif //qdoc
266
267 QT_END_NAMESPACE
268 QT_END_HEADER
269
270 #endif // QT_NO_CONCURRENT
271
272 #endif