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
50QT_BEGIN_NAMESPACE
51
52
53namespace QtConcurrent {
54
55// map kernel, works with both parallel-for and parallel-while
56template <typename Iterator, typename MapFunctor>
57class MapKernel : public IterateKernel<Iterator, void>
58{
59 MapFunctor map;
60public:
61 typedef void ReturnType;
62 MapKernel(Iterator begin, Iterator end, MapFunctor _map)
63 : IterateKernel<Iterator, void>(begin, end), map(_map)
64 { }
65
66 bool runIteration(Iterator it, int, void *) override
67 {
68 map(*it);
69 return false;
70 }
71
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
85template <typename ReducedResultType,
86 typename Iterator,
87 typename MapFunctor,
88 typename ReduceFunctor,
89 typename Reducer = ReduceKernel<ReduceFunctor,
90 ReducedResultType,
91 typename MapFunctor::result_type> >
92class MappedReducedKernel : public IterateKernel<Iterator, ReducedResultType>
93{
94 ReducedResultType reducedResult;
95 MapFunctor map;
96 ReduceFunctor reduce;
97 Reducer reducer;
98public:
99 typedef ReducedResultType ReturnType;
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
104 MappedReducedKernel(ReducedResultType initialValue,
105 MapFunctor _map,
106 ReduceFunctor _reduce)
107 : reducedResult(initialValue), map(_map), reduce(_reduce)
108 { }
109
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
121 bool runIterations(Iterator sequenceBeginIterator, int begin, int end, ReducedResultType *) override
122 {
123 IntermediateResults<typename MapFunctor::result_type> results;
124 results.begin = begin;
125 results.end = end;
126 results.vector.reserve(end - begin);
127
128 Iterator it = sequenceBeginIterator;
129 std::advance(it, begin);
130 for (int i = begin; i < end; ++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
139 void finish() override
140 {
141 reducer.finish(reduce, reducedResult);
142 }
143
144 bool shouldThrottleThread() override
145 {
146 return IterateKernel<Iterator, ReducedResultType>::shouldThrottleThread() || reducer.shouldThrottle();
147 }
148
149 bool shouldStartThread() override
150 {
151 return IterateKernel<Iterator, ReducedResultType>::shouldStartThread() && reducer.shouldStartThread();
152 }
153
154 typedef ReducedResultType ResultType;
155 ReducedResultType *result() override
156 {
157 return &reducedResult;
158 }
159};
160
161template <typename Iterator, typename MapFunctor>
162class MappedEachKernel : public IterateKernel<Iterator, typename MapFunctor::result_type>
163{
164 MapFunctor map;
165 typedef typename MapFunctor::result_type T;
166public:
167 typedef T ReturnType;
168 typedef T ResultType;
169
170 MappedEachKernel(Iterator begin, Iterator end, MapFunctor _map)
171 : IterateKernel<Iterator, T>(begin, end), map(_map) { }
172
173 bool runIteration(Iterator it, int, T *result) override
174 {
175 *result = map(*it);
176 return true;
177 }
178
179 bool runIterations(Iterator sequenceBeginIterator, int begin, int end, T *results) override
180 {
181
182 Iterator it = sequenceBeginIterator;
183 std::advance(it, begin);
184 for (int i = begin; i < end; ++i) {
185 runIteration(it, i, results + (i - begin));
186 std::advance(it, 1);
187 }
188
189 return true;
190 }
191};
192
193//! [qtconcurrentmapkernel-1]
194template <typename Iterator, typename Functor>
195inline 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]
201template <typename T, typename Iterator, typename Functor>
202inline 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*/
211template <typename Sequence, typename Base, typename Functor>
212struct SequenceHolder1 : public Base
213{
214 SequenceHolder1(const Sequence &_sequence, Functor functor)
215 : Base(_sequence.begin(), _sequence.end(), functor), sequence(_sequence)
216 { }
217
218 Sequence sequence;
219
220 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]
230template <typename T, typename Sequence, typename Functor>
231inline 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]
241template <typename IntermediateType, typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor>
242inline 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]
254template <typename IntermediateType, typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
255inline 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
267QT_END_NAMESPACE
268
269#endif // QT_NO_CONCURRENT
270
271#endif
272