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