1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#ifndef QTCONCURRENT_MAPKERNEL_H
6#define QTCONCURRENT_MAPKERNEL_H
7
8#include <QtConcurrent/qtconcurrent_global.h>
9
10#if !defined(QT_NO_CONCURRENT) || defined (Q_QDOC)
11
12#include <QtConcurrent/qtconcurrentiteratekernel.h>
13#include <QtConcurrent/qtconcurrentreducekernel.h>
14#include <QtConcurrent/qtconcurrentfunctionwrappers.h>
15
16QT_BEGIN_NAMESPACE
17
18
19namespace QtConcurrent {
20
21// map kernel, works with both parallel-for and parallel-while
22template <typename Iterator, typename MapFunctor>
23class MapKernel : public IterateKernel<Iterator, void>
24{
25 MapFunctor map;
26public:
27 typedef void ReturnType;
28 template <typename F = MapFunctor>
29 MapKernel(QThreadPool *pool, Iterator begin, Iterator end, F &&_map)
30 : IterateKernel<Iterator, void>(pool, begin, end), map(std::forward<F>(_map))
31 { }
32
33 bool runIteration(Iterator it, int, void *) override
34 {
35 std::invoke(map, *it);
36 return false;
37 }
38
39 bool runIterations(Iterator sequenceBeginIterator, int beginIndex, int endIndex, void *) override
40 {
41 Iterator it = sequenceBeginIterator;
42 std::advance(it, beginIndex);
43 for (int i = beginIndex; i < endIndex; ++i) {
44 runIteration(it, i, nullptr);
45 std::advance(it, 1);
46 }
47
48 return false;
49 }
50};
51
52template <typename ReducedResultType,
53 typename Iterator,
54 typename MapFunctor,
55 typename ReduceFunctor,
56 typename Reducer = ReduceKernel<ReduceFunctor,
57 ReducedResultType,
58 QtPrivate::MapResultType<Iterator, MapFunctor>>>
59class MappedReducedKernel : public IterateKernel<Iterator, ReducedResultType>
60{
61 ReducedResultType &reducedResult;
62 MapFunctor map;
63 ReduceFunctor reduce;
64 Reducer reducer;
65 using IntermediateResultsType = QtPrivate::MapResultType<Iterator, MapFunctor>;
66
67public:
68 typedef ReducedResultType ReturnType;
69
70 template<typename F1 = MapFunctor, typename F2 = ReduceFunctor>
71 MappedReducedKernel(QThreadPool *pool, Iterator begin, Iterator end, F1 &&_map, F2 &&_reduce,
72 ReduceOptions reduceOptions)
73 : IterateKernel<Iterator, ReducedResultType>(pool, begin, end),
74 reducedResult(this->defaultValue.value),
75 map(std::forward<F1>(_map)),
76 reduce(std::forward<F2>(_reduce)),
77 reducer(pool, reduceOptions)
78 { }
79
80 template<typename F1 = MapFunctor, typename F2 = ReduceFunctor>
81 MappedReducedKernel(QThreadPool *pool, Iterator begin, Iterator end, F1 &&_map, F2 &&_reduce,
82 ReducedResultType &&initialValue, ReduceOptions reduceOptions)
83 : IterateKernel<Iterator, ReducedResultType>(pool, begin, end,
84 std::forward<ReducedResultType>(initialValue)),
85 reducedResult(this->defaultValue.value),
86 map(std::forward<F1>(_map)),
87 reduce(std::forward<F2>(_reduce)),
88 reducer(pool, reduceOptions)
89 {
90 }
91
92 bool runIteration(Iterator it, int index, ReducedResultType *) override
93 {
94 IntermediateResults<IntermediateResultsType> results;
95 results.begin = index;
96 results.end = index + 1;
97
98 results.vector.append(std::invoke(map, *it));
99 reducer.runReduce(reduce, reducedResult, results);
100 return false;
101 }
102
103 bool runIterations(Iterator sequenceBeginIterator, int beginIndex, int endIndex, ReducedResultType *) override
104 {
105 IntermediateResults<IntermediateResultsType> results;
106 results.begin = beginIndex;
107 results.end = endIndex;
108 results.vector.reserve(endIndex - beginIndex);
109
110 Iterator it = sequenceBeginIterator;
111 std::advance(it, beginIndex);
112 for (int i = beginIndex; i < endIndex; ++i) {
113 results.vector.append(std::invoke(map, *it));
114 std::advance(it, 1);
115 }
116
117 reducer.runReduce(reduce, reducedResult, results);
118 return false;
119 }
120
121 void finish() override
122 {
123 reducer.finish(reduce, reducedResult);
124 }
125
126 bool shouldThrottleThread() override
127 {
128 return IterateKernel<Iterator, ReducedResultType>::shouldThrottleThread() || reducer.shouldThrottle();
129 }
130
131 bool shouldStartThread() override
132 {
133 return IterateKernel<Iterator, ReducedResultType>::shouldStartThread() && reducer.shouldStartThread();
134 }
135
136 typedef ReducedResultType ResultType;
137 ReducedResultType *result() override
138 {
139 return &reducedResult;
140 }
141};
142
143template <typename Iterator, typename MapFunctor>
144class MappedEachKernel : public IterateKernel<Iterator, QtPrivate::MapResultType<Iterator, MapFunctor>>
145{
146 MapFunctor map;
147 using T = QtPrivate::MapResultType<Iterator, MapFunctor>;
148
149public:
150 template <typename F = MapFunctor>
151 MappedEachKernel(QThreadPool *pool, Iterator begin, Iterator end, F &&_map)
152 : IterateKernel<Iterator, T>(pool, begin, end), map(std::forward<F>(_map))
153 { }
154
155 bool runIteration(Iterator it, int, T *result) override
156 {
157 *result = std::invoke(map, *it);
158 return true;
159 }
160
161 bool runIterations(Iterator sequenceBeginIterator, int beginIndex, int endIndex, T *results) override
162 {
163
164 Iterator it = sequenceBeginIterator;
165 std::advance(it, beginIndex);
166 for (int i = beginIndex; i < endIndex; ++i) {
167 runIteration(it, i, result: results + (i - beginIndex));
168 std::advance(it, 1);
169 }
170
171 return true;
172 }
173};
174
175//! [qtconcurrentmapkernel-1]
176template <typename Iterator, typename Functor>
177inline ThreadEngineStarter<void> startMap(QThreadPool *pool, Iterator begin,
178 Iterator end, Functor &&functor)
179{
180 return startThreadEngine(new MapKernel<Iterator, std::decay_t<Functor>>(
181 pool, begin, end, std::forward<Functor>(functor)));
182}
183
184//! [qtconcurrentmapkernel-2]
185template <typename T, typename Iterator, typename Functor>
186inline ThreadEngineStarter<T> startMapped(QThreadPool *pool, Iterator begin,
187 Iterator end, Functor &&functor)
188{
189 return startThreadEngine(new MappedEachKernel<Iterator, std::decay_t<Functor>>(
190 pool, begin, end, std::forward<Functor>(functor)));
191}
192
193/*
194 The SequnceHolder class is used to hold a reference to the
195 sequence we are working on.
196*/
197template <typename Sequence, typename Base, typename Functor>
198struct SequenceHolder1 : private QtPrivate::SequenceHolder<Sequence>, public Base
199{
200 template<typename S = Sequence, typename F = Functor>
201 SequenceHolder1(QThreadPool *pool, S &&_sequence, F &&functor)
202 : QtPrivate::SequenceHolder<Sequence>(std::forward<S>(_sequence)),
203 Base(pool, this->sequence.cbegin(), this->sequence.cend(), std::forward<F>(functor))
204 { }
205
206 void finish() override
207 {
208 Base::finish();
209 // Clear the sequence to make sure all temporaries are destroyed
210 // before finished is signaled.
211 this->sequence = Sequence();
212 }
213};
214
215//! [qtconcurrentmapkernel-3]
216template <typename T, typename Sequence, typename Functor>
217inline ThreadEngineStarter<T> startMapped(QThreadPool *pool, Sequence &&sequence,
218 Functor &&functor)
219{
220 using DecayedSequence = std::decay_t<Sequence>;
221 using DecayedFunctor = std::decay_t<Functor>;
222 using SequenceHolderType = SequenceHolder1<
223 DecayedSequence,
224 MappedEachKernel<typename DecayedSequence::const_iterator, DecayedFunctor>,
225 DecayedFunctor>;
226
227 return startThreadEngine(new SequenceHolderType(pool, std::forward<Sequence>(sequence),
228 std::forward<Functor>(functor)));
229}
230
231//! [qtconcurrentmapkernel-4]
232template <typename IntermediateType, typename ResultType, typename Sequence, typename MapFunctor,
233 typename ReduceFunctor>
234inline ThreadEngineStarter<ResultType> startMappedReduced(QThreadPool *pool,
235 Sequence &&sequence,
236 MapFunctor &&mapFunctor,
237 ReduceFunctor &&reduceFunctor,
238 ReduceOptions options)
239{
240 using DecayedSequence = std::decay_t<Sequence>;
241 using DecayedMapFunctor = std::decay_t<MapFunctor>;
242 using DecayedReduceFunctor = std::decay_t<ReduceFunctor>;
243 using Iterator = typename DecayedSequence::const_iterator;
244 using Reducer = ReduceKernel<DecayedReduceFunctor, ResultType, IntermediateType>;
245 using MappedReduceType = MappedReducedKernel<ResultType, Iterator, DecayedMapFunctor,
246 DecayedReduceFunctor, Reducer>;
247 using SequenceHolderType = SequenceHolder2<DecayedSequence, MappedReduceType, DecayedMapFunctor,
248 DecayedReduceFunctor>;
249 return startThreadEngine(new SequenceHolderType(pool, std::forward<Sequence>(sequence),
250 std::forward<MapFunctor>(mapFunctor),
251 std::forward<ReduceFunctor>(reduceFunctor),
252 options));
253}
254
255//! [qtconcurrentmapkernel-5]
256template <typename IntermediateType, typename ResultType, typename Iterator, typename MapFunctor,
257 typename ReduceFunctor>
258inline ThreadEngineStarter<ResultType> startMappedReduced(QThreadPool *pool,
259 Iterator begin,
260 Iterator end,
261 MapFunctor &&mapFunctor,
262 ReduceFunctor &&reduceFunctor,
263 ReduceOptions options)
264{
265 using Reducer =
266 ReduceKernel<std::decay_t<ReduceFunctor>, std::decay_t<ResultType>, IntermediateType>;
267 using MappedReduceType = MappedReducedKernel<ResultType, Iterator, std::decay_t<MapFunctor>,
268 std::decay_t<ReduceFunctor>, Reducer>;
269 return startThreadEngine(new MappedReduceType(pool, begin, end,
270 std::forward<MapFunctor>(mapFunctor),
271 std::forward<ReduceFunctor>(reduceFunctor),
272 options));
273}
274
275//! [qtconcurrentmapkernel-6]
276template <typename IntermediateType, typename ResultType, typename Sequence, typename MapFunctor,
277 typename ReduceFunctor>
278inline ThreadEngineStarter<ResultType> startMappedReduced(QThreadPool *pool,
279 Sequence &&sequence,
280 MapFunctor &&mapFunctor,
281 ReduceFunctor &&reduceFunctor,
282 ResultType &&initialValue,
283 ReduceOptions options)
284{
285 using DecayedSequence = std::decay_t<Sequence>;
286 using DecayedMapFunctor = std::decay_t<MapFunctor>;
287 using DecayedReduceFunctor = std::decay_t<ReduceFunctor>;
288 using Iterator = typename DecayedSequence::const_iterator;
289 using Reducer = ReduceKernel<DecayedReduceFunctor, ResultType, IntermediateType>;
290 using MappedReduceType = MappedReducedKernel<ResultType, Iterator, DecayedMapFunctor,
291 DecayedReduceFunctor, Reducer>;
292 using SequenceHolderType = SequenceHolder2<DecayedSequence, MappedReduceType, DecayedMapFunctor,
293 DecayedReduceFunctor>;
294 return startThreadEngine(
295 new SequenceHolderType(pool, std::forward<Sequence>(sequence),
296 std::forward<MapFunctor>(mapFunctor),
297 std::forward<ReduceFunctor>(reduceFunctor),
298 std::forward<ResultType>(initialValue), options));
299}
300
301//! [qtconcurrentmapkernel-7]
302template <typename IntermediateType, typename ResultType, typename Iterator, typename MapFunctor,
303 typename ReduceFunctor>
304inline ThreadEngineStarter<ResultType> startMappedReduced(QThreadPool *pool,
305 Iterator begin,
306 Iterator end,
307 MapFunctor &&mapFunctor,
308 ReduceFunctor &&reduceFunctor,
309 ResultType &&initialValue,
310 ReduceOptions options)
311{
312 using Reducer = ReduceKernel<std::decay_t<ReduceFunctor>, ResultType, IntermediateType>;
313 using MappedReduceType = MappedReducedKernel<ResultType, Iterator, std::decay_t<MapFunctor>,
314 std::decay_t<ReduceFunctor>, Reducer>;
315 return startThreadEngine(new MappedReduceType(pool, begin, end,
316 std::forward<MapFunctor>(mapFunctor),
317 std::forward<ReduceFunctor>(reduceFunctor),
318 std::forward<ResultType>(initialValue), options));
319}
320
321} // namespace QtConcurrent
322
323
324QT_END_NAMESPACE
325
326#endif // QT_NO_CONCURRENT
327
328#endif
329

source code of qtbase/src/concurrent/qtconcurrentmapkernel.h