1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtConcurrent 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 The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39
40 #ifndef QTCONCURRENT_MAPKERNEL_H
41 #define QTCONCURRENT_MAPKERNEL_H
42
43 #include <QtConcurrent/qtconcurrent_global.h>
44
45 #if !defined(QT_NO_CONCURRENT) || defined (Q_CLANG_QDOC)
46
47 #include <QtConcurrent/qtconcurrentiteratekernel.h>
48 #include <QtConcurrent/qtconcurrentreducekernel.h>
49
50 QT_BEGIN_NAMESPACE
51
52
53 namespace QtConcurrent {
54
55 // map kernel, works with both parallel-for and parallel-while
56 template <typename Iterator, typename MapFunctor>
57 class MapKernel : public IterateKernel<Iterator, void>
58 {
59 MapFunctor map;
60 public:
61 typedef void ReturnType;
MapKernel(Iterator begin,Iterator end,MapFunctor _map)62 MapKernel(Iterator begin, Iterator end, MapFunctor _map)
63 : IterateKernel<Iterator, void>(begin, end), map(_map)
64 { }
65
runIteration(Iterator it,int,void *)66 bool runIteration(Iterator it, int, void *) override
67 {
68 map(*it);
69 return false;
70 }
71
runIterations(Iterator sequenceBeginIterator,int beginIndex,int endIndex,void *)72 bool runIterations(Iterator sequenceBeginIterator, int beginIndex, int endIndex, void *) override
73 {
74 Iterator it = sequenceBeginIterator;
75 std::advance(it, beginIndex);
76 for (int i = beginIndex; i < endIndex; ++i) {
77 runIteration(it, i, nullptr);
78 std::advance(it, 1);
79 }
80
81 return false;
82 }
83 };
84
85 template <typename ReducedResultType,
86 typename Iterator,
87 typename MapFunctor,
88 typename ReduceFunctor,
89 typename Reducer = ReduceKernel<ReduceFunctor,
90 ReducedResultType,
91 typename MapFunctor::result_type> >
92 class MappedReducedKernel : public IterateKernel<Iterator, ReducedResultType>
93 {
94 ReducedResultType reducedResult;
95 MapFunctor map;
96 ReduceFunctor reduce;
97 Reducer reducer;
98 public:
99 typedef ReducedResultType ReturnType;
MappedReducedKernel(Iterator begin,Iterator end,MapFunctor _map,ReduceFunctor _reduce,ReduceOptions reduceOptions)100 MappedReducedKernel(Iterator begin, Iterator end, MapFunctor _map, ReduceFunctor _reduce, ReduceOptions reduceOptions)
101 : IterateKernel<Iterator, ReducedResultType>(begin, end), reducedResult(), map(_map), reduce(_reduce), reducer(reduceOptions)
102 { }
103
MappedReducedKernel(ReducedResultType initialValue,MapFunctor _map,ReduceFunctor _reduce)104 MappedReducedKernel(ReducedResultType initialValue,
105 MapFunctor _map,
106 ReduceFunctor _reduce)
107 : reducedResult(initialValue), map(_map), reduce(_reduce)
108 { }
109
runIteration(Iterator it,int index,ReducedResultType *)110 bool runIteration(Iterator it, int index, ReducedResultType *) override
111 {
112 IntermediateResults<typename MapFunctor::result_type> results;
113 results.begin = index;
114 results.end = index + 1;
115
116 results.vector.append(map(*it));
117 reducer.runReduce(reduce, reducedResult, results);
118 return false;
119 }
120
runIterations(Iterator sequenceBeginIterator,int beginIndex,int endIndex,ReducedResultType *)121 bool runIterations(Iterator sequenceBeginIterator, int beginIndex, int endIndex, ReducedResultType *) override
122 {
123 IntermediateResults<typename MapFunctor::result_type> results;
124 results.begin = beginIndex;
125 results.end = endIndex;
126 results.vector.reserve(endIndex - beginIndex);
127
128 Iterator it = sequenceBeginIterator;
129 std::advance(it, beginIndex);
130 for (int i = beginIndex; i < endIndex; ++i) {
131 results.vector.append(map(*(it)));
132 std::advance(it, 1);
133 }
134
135 reducer.runReduce(reduce, reducedResult, results);
136 return false;
137 }
138
finish()139 void finish() override
140 {
141 reducer.finish(reduce, reducedResult);
142 }
143
shouldThrottleThread()144 bool shouldThrottleThread() override
145 {
146 return IterateKernel<Iterator, ReducedResultType>::shouldThrottleThread() || reducer.shouldThrottle();
147 }
148
shouldStartThread()149 bool shouldStartThread() override
150 {
151 return IterateKernel<Iterator, ReducedResultType>::shouldStartThread() && reducer.shouldStartThread();
152 }
153
154 typedef ReducedResultType ResultType;
result()155 ReducedResultType *result() override
156 {
157 return &reducedResult;
158 }
159 };
160
161 template <typename Iterator, typename MapFunctor>
162 class MappedEachKernel : public IterateKernel<Iterator, typename MapFunctor::result_type>
163 {
164 MapFunctor map;
165 typedef typename MapFunctor::result_type T;
166 public:
167 typedef T ReturnType;
168 typedef T ResultType;
169
MappedEachKernel(Iterator begin,Iterator end,MapFunctor _map)170 MappedEachKernel(Iterator begin, Iterator end, MapFunctor _map)
171 : IterateKernel<Iterator, T>(begin, end), map(_map) { }
172
runIteration(Iterator it,int,T * result)173 bool runIteration(Iterator it, int, T *result) override
174 {
175 *result = map(*it);
176 return true;
177 }
178
runIterations(Iterator sequenceBeginIterator,int beginIndex,int endIndex,T * results)179 bool runIterations(Iterator sequenceBeginIterator, int beginIndex, int endIndex, T *results) override
180 {
181
182 Iterator it = sequenceBeginIterator;
183 std::advance(it, beginIndex);
184 for (int i = beginIndex; i < endIndex; ++i) {
185 runIteration(it, i, results + (i - beginIndex));
186 std::advance(it, 1);
187 }
188
189 return true;
190 }
191 };
192
193 //! [qtconcurrentmapkernel-1]
194 template <typename Iterator, typename Functor>
startMap(Iterator begin,Iterator end,Functor functor)195 inline ThreadEngineStarter<void> startMap(Iterator begin, Iterator end, Functor functor)
196 {
197 return startThreadEngine(new MapKernel<Iterator, Functor>(begin, end, functor));
198 }
199
200 //! [qtconcurrentmapkernel-2]
201 template <typename T, typename Iterator, typename Functor>
startMapped(Iterator begin,Iterator end,Functor functor)202 inline ThreadEngineStarter<T> startMapped(Iterator begin, Iterator end, Functor functor)
203 {
204 return startThreadEngine(new MappedEachKernel<Iterator, Functor>(begin, end, functor));
205 }
206
207 /*
208 The SequnceHolder class is used to hold a reference to the
209 sequence we are working on.
210 */
211 template <typename Sequence, typename Base, typename Functor>
212 struct SequenceHolder1 : public Base
213 {
SequenceHolder1SequenceHolder1214 SequenceHolder1(const Sequence &_sequence, Functor functor)
215 : Base(_sequence.begin(), _sequence.end(), functor), sequence(_sequence)
216 { }
217
218 Sequence sequence;
219
finishSequenceHolder1220 void finish() override
221 {
222 Base::finish();
223 // Clear the sequence to make sure all temporaries are destroyed
224 // before finished is signaled.
225 sequence = Sequence();
226 }
227 };
228
229 //! [qtconcurrentmapkernel-3]
230 template <typename T, typename Sequence, typename Functor>
startMapped(const Sequence & sequence,Functor functor)231 inline ThreadEngineStarter<T> startMapped(const Sequence &sequence, Functor functor)
232 {
233 typedef SequenceHolder1<Sequence,
234 MappedEachKernel<typename Sequence::const_iterator , Functor>, Functor>
235 SequenceHolderType;
236
237 return startThreadEngine(new SequenceHolderType(sequence, functor));
238 }
239
240 //! [qtconcurrentmapkernel-4]
241 template <typename IntermediateType, typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor>
startMappedReduced(const Sequence & sequence,MapFunctor mapFunctor,ReduceFunctor reduceFunctor,ReduceOptions options)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 //! [qtconcurrentmapkernel-5]
254 template <typename IntermediateType, typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
startMappedReduced(Iterator begin,Iterator end,MapFunctor mapFunctor,ReduceFunctor reduceFunctor,ReduceOptions options)255 inline ThreadEngineStarter<ResultType> startMappedReduced(Iterator begin, Iterator end,
256 MapFunctor mapFunctor, ReduceFunctor reduceFunctor,
257 ReduceOptions options)
258 {
259 typedef ReduceKernel<ReduceFunctor, ResultType, IntermediateType> Reducer;
260 typedef MappedReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer> MappedReduceType;
261 return startThreadEngine(new MappedReduceType(begin, end, mapFunctor, reduceFunctor, options));
262 }
263
264 } // namespace QtConcurrent
265
266
267 QT_END_NAMESPACE
268
269 #endif // QT_NO_CONCURRENT
270
271 #endif
272