QtConcurrent: filter- and map-reduce with initial value

It takes any type which is implictly covertible to the result type
and then converts it in the outer-layers. Then it passes it into the
deeper layers and initiales the result value.

One drive-by fix with a missing letter in the documentation.

[ChangeLog][QtConcurrent] QtConcurrent::mappedReduce and
QtConcurrent::filteredReduced, as well as their blocking variants,
now optionally take an initial value.

Fixes: QTBUG-73240
Change-Id: I7a80d96693cfa3374847c75c75b3167664609c1a
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
This commit is contained in:
Mårten Nordheim 2020-02-26 18:06:49 +01:00
parent d50b22e75d
commit d57adfe5f3
9 changed files with 1309 additions and 19 deletions

View File

@ -93,7 +93,7 @@
\section1 Concurrent Filter-Reduce
QtConcurrent::filteredReduced() is similar to QtConcurrent::filtered(),
but instead of returing a sequence with the filtered results, the results
but instead of returning a sequence with the filtered results, the results
are combined into a single value using a reduce function.
The reduce function must be of the form:
@ -266,6 +266,27 @@
\sa {Concurrent Filter and Filter-Reduce}
*/
/*!
\fn template <typename ResultType, typename Sequence, typename KeepFunctor, typename ReduceFunctor, typename InitialValueType> QFuture<ResultType> QtConcurrent::filteredReduced(const Sequence &sequence, KeepFunctor filterFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions)
Calls \a filterFunction once for each item in \a sequence. If
\a filterFunction returns \c true for an item, that item is then passed to
\a reduceFunction. In other words, the return value is the result of
\a reduceFunction for each item where \a filterFunction returns \c true.
The result value is initialized to \a initialValue when the function is
called, and the first call to \a reduceFunction will operate on
this value.
Note that while \a filterFunction is called concurrently, only one thread
at a time will call \a reduceFunction. The order in which \a reduceFunction
is called is undefined if \a reduceOptions is
QtConcurrent::UnorderedReduce. If \a reduceOptions is
QtConcurrent::OrderedReduce, \a reduceFunction is called in the order of
the original sequence.
\sa {Concurrent Filter and Filter-Reduce}
*/
/*!
\fn template <typename ResultType, typename Iterator, typename KeepFunctor, typename ReduceFunctor> QFuture<ResultType> QtConcurrent::filteredReduced(Iterator begin, Iterator end, KeepFunctor filterFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions)
@ -284,6 +305,27 @@
\sa {Concurrent Filter and Filter-Reduce}
*/
/*!
\fn template <typename ResultType, typename Iterator, typename KeepFunctor, typename ReduceFunctor, typename InitialValueType> QFuture<ResultType> QtConcurrent::filteredReduced(Iterator begin, Iterator end, KeepFunctor filterFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions)
Calls \a filterFunction once for each item from \a begin to \a end. If
\a filterFunction returns \c true for an item, that item is then passed to
\a reduceFunction. In other words, the return value is the result of
\a reduceFunction for each item where \a filterFunction returns \c true.
The result value is initialized to \a initialValue when the function is
called, and the first call to \a reduceFunction will operate on
this value.
Note that while \a filterFunction is called concurrently, only one thread
at a time will call \a reduceFunction. The order in which
\a reduceFunction is called is undefined if \a reduceOptions is
QtConcurrent::UnorderedReduce. If \a reduceOptions is
QtConcurrent::OrderedReduce, the \a reduceFunction is called in the order
of the original sequence.
\sa {Concurrent Filter and Filter-Reduce}
*/
/*!
\fn template <typename Sequence, typename KeepFunctor> void QtConcurrent::blockingFilter(Sequence &sequence, KeepFunctor filterFunction)
@ -343,6 +385,29 @@
\sa filteredReduced(), {Concurrent Filter and Filter-Reduce}
*/
/*!
\fn template <typename ResultType, typename Sequence, typename KeepFunctor, typename ReduceFunctor, typename InitialValueType> ResultType QtConcurrent::blockingFilteredReduced(const Sequence &sequence, KeepFunctor filterFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions)
Calls \a filterFunction once for each item in \a sequence. If
\a filterFunction returns \c true for an item, that item is then passed to
\a reduceFunction. In other words, the return value is the result of
\a reduceFunction for each item where \a filterFunction returns \c true.
The result value is initialized to \a initialValue when the function is
called, and the first call to \a reduceFunction will operate on
this value.
Note that while \a filterFunction is called concurrently, only one thread
at a time will call \a reduceFunction. The order in which \a reduceFunction
is called is undefined if \a reduceOptions is
QtConcurrent::UnorderedReduce. If \a reduceOptions is
QtConcurrent::OrderedReduce, \a reduceFunction is called in the order of
the original sequence.
\note This function will block until all items in the sequence have been processed.
\sa filteredReduced(), {Concurrent Filter and Filter-Reduce}
*/
/*!
\fn template <typename ResultType, typename Iterator, typename KeepFunctor, typename ReduceFunctor> ResultType QtConcurrent::blockingFilteredReduced(Iterator begin, Iterator end, KeepFunctor filterFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions)
@ -364,6 +429,30 @@
\sa filteredReduced(), {Concurrent Filter and Filter-Reduce}
*/
/*!
\fn template <typename ResultType, typename Iterator, typename KeepFunctor, typename ReduceFunctor, typename InitialValueType> ResultType QtConcurrent::blockingFilteredReduced(Iterator begin, Iterator end, KeepFunctor filterFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions)
Calls \a filterFunction once for each item from \a begin to \a end. If
\a filterFunction returns \c true for an item, that item is then passed to
\a reduceFunction. In other words, the return value is the result of
\a reduceFunction for each item where \a filterFunction returns \c true.
The result value is initialized to \a initialValue when the function is
called, and the first call to \a reduceFunction will operate on
this value.
Note that while \a filterFunction is called concurrently, only one thread
at a time will call \a reduceFunction. The order in which
\a reduceFunction is called is undefined if \a reduceOptions is
QtConcurrent::UnorderedReduce. If \a reduceOptions is
QtConcurrent::OrderedReduce, the \a reduceFunction is called in the order
of the original sequence.
\note This function will block until the iterator reaches the end of the
sequence being processed.
\sa filteredReduced(), {Concurrent Filter and Filter-Reduce}
*/
/*!
\fn [QtConcurrent-2] ThreadEngineStarter<typename qValueType<Iterator>::value_type> QtConcurrent::startFiltered(Iterator begin, Iterator end, KeepFunctor functor)
\internal
@ -384,3 +473,12 @@
\internal
*/
/*!
\fn [QtConcurrent-6] ThreadEngineStarter<ResultType> QtConcurrent::startFilteredReduced(Iterator begin, Iterator end, MapFunctor mapFunctor, ReduceFunctor reduceFunctor, ResultType initialValue, ReduceOptions options)
\internal
*/
/*!
\fn [QtConcurrent-7] ThreadEngineStarter<ResultType> QtConcurrent::startFilteredReduced(Iterator begin, Iterator end, MapFunctor mapFunctor, ReduceFunctor reduceFunctor, ResultType initialValue, ReduceOptions options)
\internal
*/

View File

@ -76,6 +76,20 @@ QFuture<ResultType> filteredReduced(const Sequence &sequence,
return startFilteredReduced<ResultType>(sequence, QtPrivate::createFunctionWrapper(keep), QtPrivate::createFunctionWrapper(reduce), options);
}
template <typename ResultType, typename Sequence, typename KeepFunctor, typename ReduceFunctor,
typename InitialValueType,
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
QFuture<ResultType> filteredReduced(const Sequence &sequence, KeepFunctor keep,
ReduceFunctor reduce, InitialValueType &&initialValue,
ReduceOptions options = ReduceOptions(UnorderedReduce
| SequentialReduce))
{
return startFilteredReduced<ResultType>(
sequence, QtPrivate::createFunctionWrapper(keep),
QtPrivate::createFunctionWrapper(reduce),
ResultType(std::forward<InitialValueType>(initialValue)), options);
}
#ifndef Q_CLANG_QDOC
template <typename Sequence, typename KeepFunctor, typename ReduceFunctor>
QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> filteredReduced(const Sequence &sequence,
@ -89,6 +103,21 @@ QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> filtere
QtPrivate::createFunctionWrapper(reduce),
options);
}
template <typename Sequence, typename KeepFunctor, typename ReduceFunctor,
typename ResultType = typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType,
typename InitialValueType,
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
QFuture<ResultType> filteredReduced(const Sequence &sequence, KeepFunctor keep,
ReduceFunctor reduce, InitialValueType &&initialValue,
ReduceOptions options = ReduceOptions(UnorderedReduce
| SequentialReduce))
{
return startFilteredReduced<ResultType>(
sequence, QtPrivate::createFunctionWrapper(keep),
QtPrivate::createFunctionWrapper(reduce),
ResultType(std::forward<InitialValueType>(initialValue)), options);
}
#endif
// filteredReduced() on iterators
@ -102,6 +131,20 @@ QFuture<ResultType> filteredReduced(Iterator begin,
return startFilteredReduced<ResultType>(begin, end, QtPrivate::createFunctionWrapper(keep), QtPrivate::createFunctionWrapper(reduce), options);
}
template <typename ResultType, typename Iterator, typename KeepFunctor, typename ReduceFunctor,
typename InitialValueType,
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
QFuture<ResultType> filteredReduced(Iterator begin, Iterator end, KeepFunctor keep,
ReduceFunctor reduce, InitialValueType &&initialValue,
ReduceOptions options = ReduceOptions(UnorderedReduce
| SequentialReduce))
{
return startFilteredReduced<ResultType>(
begin, end, QtPrivate::createFunctionWrapper(keep),
QtPrivate::createFunctionWrapper(reduce),
ResultType(std::forward<InitialValueType>(initialValue)), options);
}
#ifndef Q_CLANG_QDOC
template <typename Iterator, typename KeepFunctor, typename ReduceFunctor>
QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> filteredReduced(Iterator begin,
@ -116,6 +159,21 @@ QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> filtere
QtPrivate::createFunctionWrapper(reduce),
options);
}
template <typename Iterator, typename KeepFunctor, typename ReduceFunctor,
typename ResultType = typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType,
typename InitialValueType,
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
QFuture<ResultType> filteredReduced(Iterator begin, Iterator end, KeepFunctor keep,
ReduceFunctor reduce, InitialValueType &&initialValue,
ReduceOptions options = ReduceOptions(UnorderedReduce
| SequentialReduce))
{
return startFilteredReduced<ResultType>(
begin, end, QtPrivate::createFunctionWrapper(keep),
QtPrivate::createFunctionWrapper(reduce),
ResultType(std::forward<InitialValueType>(initialValue)), options);
}
#endif
// filtered() on sequences
@ -150,6 +208,21 @@ ResultType blockingFilteredReduced(const Sequence &sequence,
.startBlocking();
}
template <typename ResultType, typename Sequence, typename KeepFunctor, typename ReduceFunctor,
typename InitialValueType,
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
ResultType blockingFilteredReduced(const Sequence &sequence, KeepFunctor keep, ReduceFunctor reduce,
InitialValueType &&initialValue,
ReduceOptions options = ReduceOptions(UnorderedReduce
| SequentialReduce))
{
return startFilteredReduced<ResultType>(
sequence, QtPrivate::createFunctionWrapper(keep),
QtPrivate::createFunctionWrapper(reduce),
ResultType(std::forward<InitialValueType>(initialValue)), options)
.startBlocking();
}
#ifndef Q_CLANG_QDOC
template <typename Sequence, typename KeepFunctor, typename ReduceFunctor>
typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingFilteredReduced(const Sequence &sequence,
@ -163,6 +236,21 @@ typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingFiltered
QtPrivate::createFunctionWrapper(reduce),
options);
}
template <typename Sequence, typename KeepFunctor, typename ReduceFunctor,
typename ResultType = typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType,
typename InitialValueType,
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
ResultType blockingFilteredReduced(const Sequence &sequence, KeepFunctor keep, ReduceFunctor reduce,
InitialValueType &&initialValue,
ReduceOptions options = ReduceOptions(UnorderedReduce
| SequentialReduce))
{
return blockingFilteredReduced<ResultType>(
sequence, QtPrivate::createFunctionWrapper(keep),
QtPrivate::createFunctionWrapper(reduce),
ResultType(std::forward<InitialValueType>(initialValue)), options);
}
#endif
// blocking filteredReduced() on iterators
@ -181,6 +269,21 @@ ResultType blockingFilteredReduced(Iterator begin,
.startBlocking();
}
template <typename ResultType, typename Iterator, typename KeepFunctor, typename ReduceFunctor,
typename InitialValueType,
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
ResultType blockingFilteredReduced(Iterator begin, Iterator end, KeepFunctor keep,
ReduceFunctor reduce, InitialValueType &&initialValue,
ReduceOptions options = ReduceOptions(UnorderedReduce
| SequentialReduce))
{
return startFilteredReduced<ResultType>(
begin, end, QtPrivate::createFunctionWrapper(keep),
QtPrivate::createFunctionWrapper(reduce),
ResultType(std::forward<InitialValueType>(initialValue)), options)
.startBlocking();
}
#ifndef Q_CLANG_QDOC
template <typename Iterator, typename KeepFunctor, typename ReduceFunctor>
typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingFilteredReduced(Iterator begin,
@ -196,6 +299,22 @@ typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingFiltered
options)
.startBlocking();
}
template <typename Iterator, typename KeepFunctor, typename ReduceFunctor,
typename ResultType = typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType,
typename InitialValueType,
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
ResultType blockingFilteredReduced(Iterator begin, Iterator end, KeepFunctor keep,
ReduceFunctor reduce, InitialValueType &&initialValue,
ReduceOptions options = ReduceOptions(UnorderedReduce
| SequentialReduce))
{
return startFilteredReduced<ResultType>(
begin, end, QtPrivate::createFunctionWrapper(keep),
QtPrivate::createFunctionWrapper(reduce),
ResultType(std::forward<InitialValueType>(initialValue)), options)
.startBlocking();
}
#endif
// blocking filtered() on sequences

View File

@ -173,14 +173,15 @@ public:
: IterateKernelType(begin, end), reducedResult(), keep(_keep), reduce(_reduce), reducer(reduceOption)
{ }
#if 0
FilteredReducedKernel(ReducedResultType initialValue,
KeepFunctor keep,
ReduceFunctor reduce,
ReduceOption reduceOption)
: reducedResult(initialValue), keep(keep), reduce(reduce), reducer(reduceOption)
{ }
#endif
FilteredReducedKernel(Iterator begin, Iterator end, KeepFunctor _keep, ReduceFunctor _reduce,
ReducedResultType &&initialValue, ReduceOptions reduceOption)
: IterateKernelType(begin, end),
reducedResult(std::forward<ReducedResultType>(initialValue)),
keep(_keep),
reduce(_reduce),
reducer(reduceOption)
{
}
bool runIteration(Iterator it, int index, ReducedResultType *) override
{
@ -337,6 +338,33 @@ inline ThreadEngineStarter<ResultType> startFilteredReduced(Iterator begin, Iter
return startThreadEngine(new FilteredReduceType(begin, end, mapFunctor, reduceFunctor, options));
}
// Repeat the two functions above, but now with an initial value!
//! [QtConcurrent-6]
template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor>
inline ThreadEngineStarter<ResultType> startFilteredReduced(const Sequence & sequence,
MapFunctor mapFunctor, ReduceFunctor reduceFunctor,
ResultType &&initialValue,
ReduceOptions options)
{
typedef typename Sequence::const_iterator Iterator;
typedef ReduceKernel<ReduceFunctor, ResultType, typename qValueType<Iterator>::value_type > Reducer;
typedef FilteredReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer> FilteredReduceType;
typedef SequenceHolder2<Sequence, FilteredReduceType, MapFunctor, ReduceFunctor> SequenceHolderType;
return startThreadEngine(new SequenceHolderType(sequence, mapFunctor, reduceFunctor, std::forward<ResultType>(initialValue), options));
}
//! [QtConcurrent-7]
template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
inline ThreadEngineStarter<ResultType> startFilteredReduced(Iterator begin, Iterator end,
MapFunctor mapFunctor, ReduceFunctor reduceFunctor,
ResultType &&initialValue,
ReduceOptions options)
{
typedef ReduceKernel<ReduceFunctor, ResultType, typename qValueType<Iterator>::value_type> Reducer;
typedef FilteredReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer> FilteredReduceType;
return startThreadEngine(new FilteredReduceType(begin, end, mapFunctor, reduceFunctor, std::forward<ResultType>(initialValue), options));
}
} // namespace QtConcurrent

View File

@ -118,6 +118,16 @@
\internal
*/
/*!
\fn [qtconcurrentmapkernel-6] ThreadEngineStarter<ResultType> QtConcurrent::startMappedReduced(const Sequence & sequence, MapFunctor mapFunctor, ReduceFunctor reduceFunctor, ResultType &&initialValue, ReduceOptions options)
\internal
*/
/*!
\fn [qtconcurrentmapkernel-7] ThreadEngineStarter<ResultType> QtConcurrent::startMappedReduced(Iterator begin, Iterator end, MapFunctor mapFunctor, ReduceFunctor reduceFunctor, ResultType &&initialValue, ReduceOptions options)
\internal
*/
/*!
\enum QtConcurrent::ReduceOption
This enum specifies the order of which results from the map or filter
@ -343,6 +353,22 @@
\sa {Concurrent Map and Map-Reduce}
*/
/*!
\fn template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor, typename InitialValueType> QFuture<ResultType> QtConcurrent::mappedReduced(const Sequence &sequence, MapFunctor mapFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions)
Calls \a mapFunction once for each item in \a sequence. The return value of
each \a mapFunction is passed to \a reduceFunction.
The result value is initialized to \a initialValue when the function is
called, and the first call to \a reduceFunction will operate on
this value.
Note that while \a mapFunction is called concurrently, only one thread at a
time will call \a reduceFunction. The order in which \a reduceFunction is
called is determined by \a reduceOptions.
\sa {Concurrent Map and Map-Reduce}
*/
/*!
\fn template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor> QFuture<ResultType> QtConcurrent::mappedReduced(Iterator begin, Iterator end, MapFunctor mapFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions)
@ -358,6 +384,24 @@
\sa {Concurrent Map and Map-Reduce}
*/
/*!
\fn template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor, typename InitialValueType> QFuture<ResultType> QtConcurrent::mappedReduced(Iterator begin, Iterator end, MapFunctor mapFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions)
Calls \a mapFunction once for each item from \a begin to \a end. The return
value of each \a mapFunction is passed to \a reduceFunction.
The result value is initialized to \a initialValue when the function is
called, and the first call to \a reduceFunction will operate on
this value.
Note that while \a mapFunction is called concurrently, only one thread at a
time will call \a reduceFunction. By default, the order in which
\a reduceFunction is called is undefined.
\note QtConcurrent::OrderedReduce results in the ordered reduction.
\sa {Concurrent Map and Map-Reduce}
*/
/*!
\fn template <typename Sequence, typename MapFunctor> void QtConcurrent::blockingMap(Sequence &sequence, MapFunctor function)
@ -426,6 +470,24 @@
\sa mapped(), {Concurrent Map and Map-Reduce}
*/
/*!
\fn template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor, typename InitialValueType> ResultType QtConcurrent::blockingMappedReduced(const Sequence &sequence, MapFunctor mapFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions)
Calls \a mapFunction once for each item in \a sequence. The return value of
each \a mapFunction is passed to \a reduceFunction.
The result value is initialized to \a initialValue when the function is
called, and the first call to \a reduceFunction will operate on
this value.
Note that while \a mapFunction is called concurrently, only one thread at a
time will call \a reduceFunction. The order in which \a reduceFunction is
called is determined by \a reduceOptions.
\note This function will block until all items in the sequence have been processed.
\sa mapped(), {Concurrent Map and Map-Reduce}
*/
/*!
\fn template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor> ResultType QtConcurrent::blockingMappedReduced(Iterator begin, Iterator end, MapFunctor mapFunction, ReduceFunctor reduceFunction, QtConcurrent::ReduceOptions reduceOptions)
@ -442,6 +504,25 @@
\sa blockingMappedReduced(), {Concurrent Map and Map-Reduce}
*/
/*!
\fn template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor, typename InitialValueType> ResultType QtConcurrent::blockingMappedReduced(Iterator begin, Iterator end, MapFunctor mapFunction, ReduceFunctor reduceFunction, InitialValueType &&initialValue, QtConcurrent::ReduceOptions reduceOptions)
Calls \a mapFunction once for each item from \a begin to \a end. The return
value of each \a mapFunction is passed to \a reduceFunction.
The result value is initialized to \a initialValue when the function is
called, and the first call to \a reduceFunction will operate on
this value.
Note that while \a mapFunction is called concurrently, only one thread at a
time will call \a reduceFunction. The order in which \a reduceFunction is
called is undefined.
\note This function will block until the iterator reaches the end of the
sequence being processed.
\sa blockingMappedReduced(), {Concurrent Map and Map-Reduce}
*/
/*!
\class QtConcurrent::FunctionWrapper0
\inmodule QtConcurrent

View File

@ -83,6 +83,21 @@ QFuture<ResultType> mappedReduced(const Sequence &sequence,
options);
}
template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor,
typename InitialValueType,
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
QFuture<ResultType> mappedReduced(const Sequence &sequence, MapFunctor map, ReduceFunctor reduce,
InitialValueType &&initialValue,
ReduceOptions options = ReduceOptions(UnorderedReduce
| SequentialReduce))
{
return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType,
ResultType>(sequence, QtPrivate::createFunctionWrapper(map),
QtPrivate::createFunctionWrapper(reduce),
ResultType(std::forward<InitialValueType>(initialValue)),
options);
}
template <typename Sequence, typename MapFunctor, typename ReduceFunctor>
QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> mappedReduced(const Sequence &sequence,
MapFunctor map,
@ -96,6 +111,22 @@ QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> mappedR
options);
}
template <typename Sequence, typename MapFunctor, typename ReduceFunctor,
typename ResultType = typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType,
typename InitialValueType,
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
QFuture<ResultType> mappedReduced(const Sequence &sequence, MapFunctor map, ReduceFunctor reduce,
InitialValueType &&initialValue,
ReduceOptions options = ReduceOptions(UnorderedReduce
| SequentialReduce))
{
return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType,
typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>(
sequence, QtPrivate::createFunctionWrapper(map),
QtPrivate::createFunctionWrapper(reduce),
ResultType(std::forward<InitialValueType>(initialValue)), options);
}
// mappedReduced() for iterators
template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
QFuture<ResultType> mappedReduced(Iterator begin,
@ -111,6 +142,21 @@ QFuture<ResultType> mappedReduced(Iterator begin,
options);
}
template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor,
typename InitialValueType,
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
QFuture<ResultType> mappedReduced(Iterator begin, Iterator end, MapFunctor map,
ReduceFunctor reduce, InitialValueType &&initialValue,
ReduceOptions options = ReduceOptions(UnorderedReduce
| SequentialReduce))
{
return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType,
ResultType>(begin, end, QtPrivate::createFunctionWrapper(map),
QtPrivate::createFunctionWrapper(reduce),
ResultType(std::forward<InitialValueType>(initialValue)),
options);
}
template <typename Iterator, typename MapFunctor, typename ReduceFunctor>
QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> mappedReduced(Iterator begin,
Iterator end,
@ -125,6 +171,22 @@ QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> mappedR
options);
}
template <typename Iterator, typename MapFunctor, typename ReduceFunctor,
typename ResultType = typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType,
typename InitialValueType,
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> mappedReduced(
Iterator begin, Iterator end, MapFunctor map, ReduceFunctor reduce,
InitialValueType &&initialValue,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType,
typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>(
begin, end, QtPrivate::createFunctionWrapper(map),
QtPrivate::createFunctionWrapper(reduce),
ResultType(std::forward<InitialValueType>(initialValue)), options);
}
// mapped() for sequences
template <typename Sequence, typename MapFunctor>
QFuture<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType> mapped(const Sequence &sequence, MapFunctor map)
@ -168,6 +230,22 @@ ResultType blockingMappedReduced(const Sequence &sequence,
.startBlocking();
}
template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor,
typename InitialValueType,
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
ResultType blockingMappedReduced(const Sequence &sequence, MapFunctor map, ReduceFunctor reduce,
InitialValueType &&initialValue,
ReduceOptions options = ReduceOptions(UnorderedReduce
| SequentialReduce))
{
return QtConcurrent::startMappedReduced<
typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, ResultType>(
sequence, QtPrivate::createFunctionWrapper(map),
QtPrivate::createFunctionWrapper(reduce),
ResultType(std::forward<InitialValueType>(initialValue)), options)
.startBlocking();
}
template <typename MapFunctor, typename ReduceFunctor, typename Sequence>
typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingMappedReduced(const Sequence &sequence,
MapFunctor map,
@ -182,6 +260,24 @@ typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingMappedRe
.startBlocking();
}
template <typename MapFunctor, typename ReduceFunctor, typename Sequence,
typename ResultType = typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType,
typename InitialValueType,
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingMappedReduced(
const Sequence &sequence, MapFunctor map, ReduceFunctor reduce,
InitialValueType &&initialValue,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
return QtConcurrent::startMappedReduced<
typename QtPrivate::MapResultType<void, MapFunctor>::ResultType,
typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>(
sequence, QtPrivate::createFunctionWrapper(map),
QtPrivate::createFunctionWrapper(reduce),
ResultType(std::forward<InitialValueType>(initialValue)), options)
.startBlocking();
}
// blockingMappedReduced() for iterator ranges
template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
ResultType blockingMappedReduced(Iterator begin,
@ -198,6 +294,23 @@ ResultType blockingMappedReduced(Iterator begin,
.startBlocking();
}
template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor,
typename InitialValueType,
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
ResultType blockingMappedReduced(Iterator begin, Iterator end, MapFunctor map, ReduceFunctor reduce,
InitialValueType &&initialValue,
QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(
QtConcurrent::UnorderedReduce
| QtConcurrent::SequentialReduce))
{
return QtConcurrent::startMappedReduced<
typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, ResultType>(
begin, end, QtPrivate::createFunctionWrapper(map),
QtPrivate::createFunctionWrapper(reduce),
ResultType(std::forward<InitialValueType>(initialValue)), options)
.startBlocking();
}
template <typename Iterator, typename MapFunctor, typename ReduceFunctor>
typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingMappedReduced(Iterator begin,
Iterator end,
@ -213,6 +326,25 @@ typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingMappedRe
.startBlocking();
}
template <typename Iterator, typename MapFunctor, typename ReduceFunctor,
typename ResultType = typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType,
typename InitialValueType,
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingMappedReduced(
Iterator begin, Iterator end, MapFunctor map, ReduceFunctor reduce,
InitialValueType &&initialValue,
QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(
QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
{
return QtConcurrent::startMappedReduced<
typename QtPrivate::MapResultType<void, MapFunctor>::ResultType,
typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>(
begin, end, QtPrivate::createFunctionWrapper(map),
QtPrivate::createFunctionWrapper(reduce),
ResultType(std::forward<InitialValueType>(initialValue)), options)
.startBlocking();
}
// mapped() for sequences with a different putput sequence type.
template <typename OutputSequence, typename InputSequence, typename MapFunctor>
OutputSequence blockingMapped(const InputSequence &sequence, MapFunctor map)

View File

@ -101,11 +101,15 @@ public:
: IterateKernel<Iterator, ReducedResultType>(begin, end), reducedResult(), map(_map), reduce(_reduce), reducer(reduceOptions)
{ }
MappedReducedKernel(ReducedResultType initialValue,
MapFunctor _map,
ReduceFunctor _reduce)
: reducedResult(initialValue), map(_map), reduce(_reduce)
{ }
MappedReducedKernel(Iterator begin, Iterator end, MapFunctor _map, ReduceFunctor _reduce,
ReducedResultType &&initialValue, ReduceOptions reduceOptions)
: IterateKernel<Iterator, ReducedResultType>(begin, end),
reducedResult(std::forward<ReducedResultType>(initialValue)),
map(_map),
reduce(_reduce),
reducer(reduceOptions)
{
}
bool runIteration(Iterator it, int index, ReducedResultType *) override
{
@ -261,6 +265,41 @@ inline ThreadEngineStarter<ResultType> startMappedReduced(Iterator begin, Iterat
return startThreadEngine(new MappedReduceType(begin, end, mapFunctor, reduceFunctor, options));
}
//! [qtconcurrentmapkernel-6]
template <typename IntermediateType, typename ResultType, typename Sequence, typename MapFunctor,
typename ReduceFunctor>
inline ThreadEngineStarter<ResultType> startMappedReduced(const Sequence &sequence,
MapFunctor mapFunctor,
ReduceFunctor reduceFunctor,
ResultType &&initialValue,
ReduceOptions options)
{
typedef typename Sequence::const_iterator Iterator;
typedef ReduceKernel<ReduceFunctor, ResultType, IntermediateType> Reducer;
typedef MappedReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer>
MappedReduceType;
typedef SequenceHolder2<Sequence, MappedReduceType, MapFunctor, ReduceFunctor>
SequenceHolderType;
return startThreadEngine(new SequenceHolderType(
sequence, mapFunctor, reduceFunctor, std::forward<ResultType>(initialValue), options));
}
//! [qtconcurrentmapkernel-7]
template <typename IntermediateType, typename ResultType, typename Iterator, typename MapFunctor,
typename ReduceFunctor>
inline ThreadEngineStarter<ResultType> startMappedReduced(Iterator begin, Iterator end,
MapFunctor mapFunctor,
ReduceFunctor reduceFunctor,
ResultType &&initialValue,
ReduceOptions options)
{
typedef ReduceKernel<ReduceFunctor, ResultType, IntermediateType> Reducer;
typedef MappedReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer>
MappedReduceType;
return startThreadEngine(new MappedReduceType(begin, end, mapFunctor, reduceFunctor,
std::forward<ResultType>(initialValue), options));
}
} // namespace QtConcurrent

View File

@ -232,6 +232,16 @@ struct SequenceHolder2 : public Base
sequence(_sequence)
{ }
template <typename InitialValueType>
SequenceHolder2(const Sequence &_sequence,
Functor1 functor1,
Functor2 functor2,
InitialValueType &&initialValue,
ReduceOptions reduceOptions)
: Base(_sequence.begin(), _sequence.end(), functor1, functor2, std::forward<InitialValueType>(initialValue), reduceOptions),
sequence(_sequence)
{ }
Sequence sequence;
void finish() override

View File

@ -44,6 +44,7 @@ private slots:
void incrementalResults();
void noDetach();
void stlContainers();
void filteredReduceInitialValue();
};
void tst_QtConcurrentFilter::filter()
@ -728,7 +729,6 @@ void tst_QtConcurrentFilter::filteredReduced()
QCOMPARE(sum, 6);
}
// ### the same as above, with an initial result value
}
bool filterfn(int i)
@ -857,5 +857,426 @@ void tst_QtConcurrentFilter::stlContainers()
QCOMPARE(*list2.begin(), 1);
}
void tst_QtConcurrentFilter::filteredReduceInitialValue()
{
// This test's the same as filteredReduce, but with an initial value on all calls
QList<int> list;
list << 1 << 2 << 3 << 4;
QList<Number> numberList;
numberList << 1 << 2 << 3 << 4;
// functor-functor
{
int sum = QtConcurrent::filteredReduced<int>(list, KeepEvenIntegers(), IntSumReduce(), 10);
QCOMPARE(sum, 16);
int sum2 = QtConcurrent::filteredReduced<int>(list, keepEvenIntegers, intSumReduce, 10);
QCOMPARE(sum2, 16);
}
{
QVector<int> vector;
vector << 1 << 2 << 3 << 4;
int sum =
QtConcurrent::filteredReduced<int>(vector, KeepEvenIntegers(), IntSumReduce(), 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::filteredReduced<int>(
list.begin(), list.end(), KeepEvenIntegers(), IntSumReduce(), 10);
QCOMPARE(sum, 16);
int sum2 = QtConcurrent::filteredReduced<int>(
list.begin(), list.end(), keepEvenIntegers, intSumReduce, 10);
QCOMPARE(sum2, 16);
}
{
int sum = QtConcurrent::filteredReduced<int>(
list.constBegin(), list.constEnd(), KeepEvenIntegers(), IntSumReduce(), 10);
QCOMPARE(sum, 16);
int sum2 = QtConcurrent::filteredReduced<int>(
list.constBegin(), list.constEnd(), keepEvenIntegers, intSumReduce, 10);
QCOMPARE(sum2, 16);
}
{
int sum = QtConcurrent::blockingFilteredReduced<int>(
list, KeepEvenIntegers(), IntSumReduce(), 10);
QCOMPARE(sum, 16);
int sum2 = QtConcurrent::blockingFilteredReduced<int>(
list, keepEvenIntegers, intSumReduce, 10);
QCOMPARE(sum2, 16);
}
{
int sum = QtConcurrent::blockingFilteredReduced<int>(
list.begin(), list.end(), KeepEvenIntegers(), IntSumReduce(), 10);
QCOMPARE(sum, 16);
int sum2 = QtConcurrent::blockingFilteredReduced<int>(
list.begin(), list.end(), keepEvenIntegers, intSumReduce, 10);
QCOMPARE(sum2, 16);
}
{
int sum = QtConcurrent::blockingFilteredReduced<int>(
list.constBegin(), list.constEnd(), KeepEvenIntegers(), IntSumReduce(), 10);
QCOMPARE(sum, 16);
int sum2 = QtConcurrent::blockingFilteredReduced<int>(
list.constBegin(), list.constEnd(), keepEvenIntegers, intSumReduce, 10);
QCOMPARE(sum2, 16);
}
// function-functor
{
int sum = QtConcurrent::filteredReduced<int>(list, keepEvenIntegers, IntSumReduce(), 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::filteredReduced<int>(
list.begin(), list.end(), keepEvenIntegers, IntSumReduce(), 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::filteredReduced<int>(
list.constBegin(), list.constEnd(), keepEvenIntegers, IntSumReduce(), 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::blockingFilteredReduced<int>(
list, keepEvenIntegers, IntSumReduce(), 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::blockingFilteredReduced<int>(
list.begin(), list.end(), keepEvenIntegers, IntSumReduce(), 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::blockingFilteredReduced<int>(
list.constBegin(), list.constEnd(), keepEvenIntegers, IntSumReduce(), 10);
QCOMPARE(sum, 16);
}
// functor-function
{
int sum = QtConcurrent::filteredReduced(list, KeepEvenIntegers(), intSumReduce, 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::filteredReduced(
list.begin(), list.end(), KeepEvenIntegers(), intSumReduce, 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::filteredReduced(
list.constBegin(), list.constEnd(), KeepEvenIntegers(), intSumReduce, 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::blockingFilteredReduced(list, KeepEvenIntegers(), intSumReduce, 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::blockingFilteredReduced(
list.begin(), list.end(), KeepEvenIntegers(), intSumReduce, 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::blockingFilteredReduced(
list.constBegin(), list.constEnd(), KeepEvenIntegers(), intSumReduce, 10);
QCOMPARE(sum, 16);
}
// function-function
{
int sum = QtConcurrent::filteredReduced(list, keepEvenIntegers, intSumReduce, 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::filteredReduced(
list.begin(), list.end(), keepEvenIntegers, intSumReduce, 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::filteredReduced(
list.constBegin(), list.constEnd(), keepEvenIntegers, intSumReduce, 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::blockingFilteredReduced(list, keepEvenIntegers, intSumReduce, 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::blockingFilteredReduced(
list.begin(), list.end(), keepEvenIntegers, intSumReduce, 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::blockingFilteredReduced(
list.constBegin(), list.constEnd(), keepEvenIntegers, intSumReduce, 10);
QCOMPARE(sum, 16);
}
auto push_back = static_cast<void (QVector<int>::*)(const int &)>(&QVector<int>::push_back);
// functor-member
QVector<int> initialIntVector;
initialIntVector.push_back(10);
{
QList<int> list2 = QtConcurrent::filteredReduced(
list, KeepEvenIntegers(), push_back, initialIntVector, QtConcurrent::OrderedReduce);
QCOMPARE(list2, QList<int>() << 10 << 2 << 4);
}
{
QList<int> list2 = QtConcurrent::filteredReduced(list.begin(),
list.end(),
KeepEvenIntegers(),
push_back,
initialIntVector,
QtConcurrent::OrderedReduce);
QCOMPARE(list2, QList<int>() << 10 << 2 << 4);
}
{
QList<int> list2 = QtConcurrent::filteredReduced(list.constBegin(),
list.constEnd(),
KeepEvenIntegers(),
push_back,
initialIntVector,
QtConcurrent::OrderedReduce);
QCOMPARE(list2, QList<int>() << 10 << 2 << 4);
}
{
QList<int> list2 = QtConcurrent::blockingFilteredReduced(
list, KeepEvenIntegers(), push_back, initialIntVector, QtConcurrent::OrderedReduce);
QCOMPARE(list2, QList<int>() << 10 << 2 << 4);
}
{
QList<int> list2 = QtConcurrent::blockingFilteredReduced(list.begin(),
list.end(),
KeepEvenIntegers(),
push_back,
initialIntVector,
QtConcurrent::OrderedReduce);
QCOMPARE(list2, QList<int>() << 10 << 2 << 4);
}
{
QList<int> list2 = QtConcurrent::blockingFilteredReduced(list.constBegin(),
list.constEnd(),
KeepEvenIntegers(),
push_back,
initialIntVector,
QtConcurrent::OrderedReduce);
QCOMPARE(list2, QList<int>() << 10 << 2 << 4);
}
// member-functor
{
int sum = QtConcurrent::filteredReduced<int>(
numberList, &Number::isEven, NumberSumReduce(), 10);
QCOMPARE(sum, 16);
int sum2 = QtConcurrent::filteredReduced<int>(
QList<Number>(numberList), &Number::isEven, NumberSumReduce(), 10);
QCOMPARE(sum2, 16);
}
{
int sum = QtConcurrent::filteredReduced<int>(
numberList.begin(), numberList.end(), &Number::isEven, NumberSumReduce(), 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::filteredReduced<int>(numberList.constBegin(),
numberList.constEnd(),
&Number::isEven,
NumberSumReduce(),
10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::blockingFilteredReduced<int>(
numberList, &Number::isEven, NumberSumReduce(), 10);
QCOMPARE(sum, 16);
int sum2 = QtConcurrent::blockingFilteredReduced<int>(
QList<Number>(numberList), &Number::isEven, NumberSumReduce(), 10);
QCOMPARE(sum2, 16);
}
{
int sum = QtConcurrent::blockingFilteredReduced<int>(
numberList.begin(), numberList.end(), &Number::isEven, NumberSumReduce(), 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::blockingFilteredReduced<int>(numberList.constBegin(),
numberList.constEnd(),
&Number::isEven,
NumberSumReduce(),
10);
QCOMPARE(sum, 16);
}
// member-member
auto push_back_number =
static_cast<void (QVector<Number>::*)(const Number &)>(&QVector<Number>::push_back);
QVector<Number> initialNumberVector { 10 };
{
QList<Number> numbers;
numbers << 1 << 2 << 3 << 4;
QList<Number> list2 = QtConcurrent::filteredReduced(numbers,
&Number::isEven,
push_back_number,
initialNumberVector,
QtConcurrent::OrderedReduce);
QCOMPARE(list2, QList<Number>() << 10 << 2 << 4);
}
{
QList<Number> numbers;
numbers << 1 << 2 << 3 << 4;
QList<Number> list2 = QtConcurrent::filteredReduced(numbers.begin(),
numbers.end(),
&Number::isEven,
push_back_number,
initialNumberVector,
QtConcurrent::OrderedReduce);
QCOMPARE(list2, QList<Number>() << 10 << 2 << 4);
}
{
QList<Number> numbers;
numbers << 1 << 2 << 3 << 4;
QList<Number> list2 = QtConcurrent::filteredReduced(numbers.constBegin(),
numbers.constEnd(),
&Number::isEven,
push_back_number,
initialNumberVector,
QtConcurrent::OrderedReduce);
QCOMPARE(list2, QList<Number>() << 10 << 2 << 4);
}
{
QList<Number> numbers;
numbers << 1 << 2 << 3 << 4;
QList<Number> list2 = QtConcurrent::blockingFilteredReduced(numbers,
&Number::isEven,
push_back_number,
initialNumberVector,
QtConcurrent::OrderedReduce);
QCOMPARE(list2, QList<Number>() << 10 << 2 << 4);
}
{
QList<Number> numbers;
numbers << 1 << 2 << 3 << 4;
QList<Number> list2 = QtConcurrent::blockingFilteredReduced(numbers.begin(),
numbers.end(),
&Number::isEven,
push_back_number,
initialNumberVector,
QtConcurrent::OrderedReduce);
QCOMPARE(list2, QList<Number>() << 10 << 2 << 4);
}
{
QList<Number> numbers;
numbers << 1 << 2 << 3 << 4;
QList<Number> list2 = QtConcurrent::blockingFilteredReduced(numbers.constBegin(),
numbers.constEnd(),
&Number::isEven,
push_back_number,
initialNumberVector,
QtConcurrent::OrderedReduce);
QCOMPARE(list2, QList<Number>() << 10 << 2 << 4);
}
// function-member
{
QList<int> list2 = QtConcurrent::filteredReduced(
list, keepEvenIntegers, push_back, initialIntVector, QtConcurrent::OrderedReduce);
QCOMPARE(list2, QList<int>() << 10 << 2 << 4);
}
{
QList<int> list2 = QtConcurrent::filteredReduced(list.begin(),
list.end(),
keepEvenIntegers,
push_back,
initialIntVector,
QtConcurrent::OrderedReduce);
QCOMPARE(list2, QList<int>() << 10 << 2 << 4);
}
{
QList<int> list2 = QtConcurrent::filteredReduced(list.constBegin(),
list.constEnd(),
keepEvenIntegers,
push_back,
initialIntVector,
QtConcurrent::OrderedReduce);
QCOMPARE(list2, QList<int>() << 10 << 2 << 4);
}
{
QList<int> list2 = QtConcurrent::blockingFilteredReduced(
list, keepEvenIntegers, push_back, initialIntVector, QtConcurrent::OrderedReduce);
QCOMPARE(list2, QList<int>() << 10 << 2 << 4);
}
{
QList<int> list2 = QtConcurrent::blockingFilteredReduced(list.begin(),
list.end(),
keepEvenIntegers,
push_back,
initialIntVector,
QtConcurrent::OrderedReduce);
QCOMPARE(list2, QList<int>() << 10 << 2 << 4);
}
{
QList<int> list2 = QtConcurrent::blockingFilteredReduced(list.constBegin(),
list.constEnd(),
keepEvenIntegers,
push_back,
initialIntVector,
QtConcurrent::OrderedReduce);
QCOMPARE(list2, QList<int>() << 10 << 2 << 4);
}
// member-function
{
int sum = QtConcurrent::filteredReduced(numberList, &Number::isEven, numberSumReduce, 10);
QCOMPARE(sum, 16);
int sum2 = QtConcurrent::filteredReduced(
QList<Number>(numberList), &Number::isEven, numberSumReduce, 10);
QCOMPARE(sum2, 16);
}
{
int sum = QtConcurrent::filteredReduced(
numberList.begin(), numberList.end(), &Number::isEven, numberSumReduce, 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::filteredReduced(numberList.constBegin(),
numberList.constEnd(),
&Number::isEven,
numberSumReduce,
10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::blockingFilteredReduced(
numberList, &Number::isEven, numberSumReduce, 10);
QCOMPARE(sum, 16);
int sum2 = QtConcurrent::blockingFilteredReduced(
QList<Number>(numberList), &Number::isEven, numberSumReduce, 10);
QCOMPARE(sum2, 16);
}
{
int sum = QtConcurrent::blockingFilteredReduced(
numberList.begin(), numberList.end(), &Number::isEven, numberSumReduce, 10);
QCOMPARE(sum, 16);
}
{
int sum = QtConcurrent::blockingFilteredReduced(numberList.constBegin(),
numberList.constEnd(),
&Number::isEven,
numberSumReduce,
10);
QCOMPARE(sum, 16);
}
}
QTEST_MAIN(tst_QtConcurrentFilter)
#include "tst_qtconcurrentfilter.moc"

View File

@ -58,6 +58,8 @@ private slots:
void qFutureAssignmentLeak();
void stressTest();
void persistentResultTest();
void mappedReducedInitialValue();
void blocking_mappedReducedInitialValue();
public slots:
void throttling();
};
@ -1084,8 +1086,6 @@ void tst_QtConcurrentMap::mappedReduced()
intSumReduce);
QCOMPARE(sum3, 6);
}
// ### the same as above, with an initial result value
}
void tst_QtConcurrentMap::blocking_mappedReduced()
@ -1271,8 +1271,6 @@ void tst_QtConcurrentMap::blocking_mappedReduced()
intSumReduce);
QCOMPARE(sum3, 6);
}
// ### the same as above, with an initial result value
}
int sleeper(int val)
@ -1767,5 +1765,369 @@ void tst_QtConcurrentMap::persistentResultTest()
QCOMPARE(ref.loadAcquire(), 3);
}
void tst_QtConcurrentMap::mappedReducedInitialValue()
{
// This is a copy of tst_QtConcurrentMap::mappedReduced with the initial value parameter added
QList<int> list;
list << 1 << 2 << 3;
QList<Number> numberList;
numberList << 1 << 2 << 3;
// test Q_DECLARE_OPERATORS_FOR_FLAGS
QtConcurrent::ReduceOptions opt =
(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce);
QVERIFY(opt);
int initialValue = 10;
// functor-functor
{
int sum = QtConcurrent::mappedReduced<int>(list, IntSquare(), IntSumReduce(), initialValue);
QCOMPARE(sum, 24);
int sum2 = QtConcurrent::mappedReduced<int>(
list.constBegin(), list.constEnd(), IntSquare(), IntSumReduce(), initialValue);
QCOMPARE(sum2, 24);
int sum3 = QtConcurrent::mappedReduced<int>(
QList<int>(list), IntSquare(), IntSumReduce(), initialValue);
QCOMPARE(sum3, 24);
int sum4 = QtConcurrent::mappedReduced<int>(list, intSquare, intSumReduce, initialValue);
QCOMPARE(sum4, 24);
int sum5 = QtConcurrent::mappedReduced<int>(
list.constBegin(), list.constEnd(), intSquare, intSumReduce, initialValue);
QCOMPARE(sum5, 24);
int sum6 = QtConcurrent::mappedReduced<int>(
QList<int>(list), intSquare, intSumReduce, initialValue);
QCOMPARE(sum6, 24);
}
// function-functor
{
int sum = QtConcurrent::mappedReduced<int>(list, intSquare, IntSumReduce(), initialValue);
QCOMPARE(sum, 24);
int sum2 = QtConcurrent::mappedReduced<int>(
list.constBegin(), list.constEnd(), intSquare, IntSumReduce(), initialValue);
QCOMPARE(sum2, 24);
int sum3 = QtConcurrent::mappedReduced<int>(
QList<int>(list), intSquare, IntSumReduce(), initialValue);
QCOMPARE(sum3, 24);
}
// functor-function
{
int sum = QtConcurrent::mappedReduced(list, IntSquare(), intSumReduce, initialValue);
QCOMPARE(sum, 24);
int sum2 = QtConcurrent::mappedReduced(
list.constBegin(), list.constEnd(), IntSquare(), intSumReduce, initialValue);
QCOMPARE(sum2, 24);
int sum3 = QtConcurrent::mappedReduced(
QList<int>(list), IntSquare(), intSumReduce, initialValue);
QCOMPARE(sum3, 24);
}
// function-function
{
int sum = QtConcurrent::mappedReduced(list, intSquare, intSumReduce, initialValue);
QCOMPARE(sum, 24);
int sum2 = QtConcurrent::mappedReduced(
list.constBegin(), list.constEnd(), intSquare, intSumReduce, initialValue);
QCOMPARE(sum2, 24);
int sum3 = QtConcurrent::mappedReduced(
QList<int>(list), intSquare, intSumReduce, initialValue);
QCOMPARE(sum3, 24);
}
auto push_back = static_cast<void (QVector<int>::*)(const int &)>(&QVector<int>::push_back);
QVector<int> initialIntVector;
initialIntVector.push_back(10);
// functor-member
{
QList<int> list2 = QtConcurrent::mappedReduced(
list, IntSquare(), push_back, initialIntVector, OrderedReduce);
QCOMPARE(list, QList<int>() << 1 << 2 << 3);
QCOMPARE(list2, QList<int>() << 10 << 1 << 4 << 9);
QList<int> list3 = QtConcurrent::mappedReduced(list.constBegin(),
list.constEnd(),
IntSquare(),
push_back,
initialIntVector,
OrderedReduce);
QCOMPARE(list, QList<int>() << 1 << 2 << 3);
QCOMPARE(list3, QList<int>() << 10 << 1 << 4 << 9);
QList<int> list4 = QtConcurrent::mappedReduced(
QList<int>(list), IntSquare(), push_back, initialIntVector, OrderedReduce);
QCOMPARE(list, QList<int>() << 1 << 2 << 3);
QCOMPARE(list4, QList<int>() << 10 << 1 << 4 << 9);
}
// member-functor
{
int sum = QtConcurrent::mappedReduced<int>(
numberList, &Number::toInt, IntSumReduce(), initialValue);
QCOMPARE(sum, 16);
int sum2 = QtConcurrent::mappedReduced<int>(numberList.constBegin(),
numberList.constEnd(),
&Number::toInt,
IntSumReduce(),
initialValue);
QCOMPARE(sum2, 16);
int sum3 = QtConcurrent::mappedReduced<int>(
QList<Number>(numberList), &Number::toInt, IntSumReduce(), initialValue);
QCOMPARE(sum3, 16);
}
// member-member
{
QList<int> list2 = QtConcurrent::mappedReduced(
numberList, &Number::toInt, push_back, initialIntVector, OrderedReduce);
QCOMPARE(list2, QList<int>() << 10 << 1 << 2 << 3);
QList<int> list3 = QtConcurrent::mappedReduced(numberList.constBegin(),
numberList.constEnd(),
&Number::toInt,
push_back,
initialIntVector,
OrderedReduce);
QCOMPARE(list3, QList<int>() << 10 << 1 << 2 << 3);
QList<int> list4 = QtConcurrent::mappedReduced(QList<Number>(numberList),
&Number::toInt,
push_back,
initialIntVector,
OrderedReduce);
QCOMPARE(list4, QList<int>() << 10 << 1 << 2 << 3);
}
// function-member
{
QList<int> list2 = QtConcurrent::mappedReduced(
list, intSquare, push_back, initialIntVector, OrderedReduce);
QCOMPARE(list, QList<int>() << 1 << 2 << 3);
QCOMPARE(list2, QList<int>() << 10 << 1 << 4 << 9);
QList<int> list3 = QtConcurrent::mappedReduced(list.constBegin(),
list.constEnd(),
intSquare,
push_back,
initialIntVector,
OrderedReduce);
QCOMPARE(list, QList<int>() << 1 << 2 << 3);
QCOMPARE(list3, QList<int>() << 10 << 1 << 4 << 9);
QList<int> list4 = QtConcurrent::mappedReduced(
QList<int>(list), intSquare, push_back, initialIntVector, OrderedReduce);
QCOMPARE(list, QList<int>() << 1 << 2 << 3);
QCOMPARE(list4, QList<int>() << 10 << 1 << 4 << 9);
}
// member-function
{
int sum =
QtConcurrent::mappedReduced(numberList, &Number::toInt, intSumReduce, initialValue);
QCOMPARE(sum, 16);
int sum2 = QtConcurrent::mappedReduced(numberList.constBegin(),
numberList.constEnd(),
&Number::toInt,
intSumReduce,
initialValue);
QCOMPARE(sum2, 16);
int sum3 = QtConcurrent::mappedReduced(
QList<Number>(numberList), &Number::toInt, intSumReduce, initialValue);
QCOMPARE(sum3, 16);
}
}
void tst_QtConcurrentMap::blocking_mappedReducedInitialValue()
{
// This is a copy of tst_QtConcurrentMap::blocking_mappedReduced with the initial value
// parameter added
QList<int> list;
list << 1 << 2 << 3;
QList<Number> numberList;
numberList << 1 << 2 << 3;
int initialValue = 10;
// functor-functor
{
int sum = QtConcurrent::blockingMappedReduced<int>(
list, IntSquare(), IntSumReduce(), initialValue);
QCOMPARE(sum, 24);
int sum2 = QtConcurrent::blockingMappedReduced<int>(
list.constBegin(), list.constEnd(), IntSquare(), IntSumReduce(), initialValue);
QCOMPARE(sum2, 24);
int sum3 = QtConcurrent::blockingMappedReduced<int>(
QList<int>(list), IntSquare(), IntSumReduce(), initialValue);
QCOMPARE(sum3, 24);
int sum4 = QtConcurrent::blockingMappedReduced<int>(
list, intSquare, intSumReduce, initialValue);
QCOMPARE(sum4, 24);
int sum5 = QtConcurrent::blockingMappedReduced<int>(
list.constBegin(), list.constEnd(), intSquare, intSumReduce, initialValue);
QCOMPARE(sum5, 24);
int sum6 = QtConcurrent::blockingMappedReduced<int>(
QList<int>(list), intSquare, intSumReduce, initialValue);
QCOMPARE(sum6, 24);
}
// function-functor
{
int sum = QtConcurrent::blockingMappedReduced<int>(
list, intSquare, IntSumReduce(), initialValue);
QCOMPARE(sum, 24);
int sum2 = QtConcurrent::blockingMappedReduced<int>(
list.constBegin(), list.constEnd(), intSquare, IntSumReduce(), initialValue);
QCOMPARE(sum2, 24);
int sum3 = QtConcurrent::blockingMappedReduced<int>(
QList<int>(list), intSquare, IntSumReduce(), initialValue);
QCOMPARE(sum3, 24);
}
// functor-function
{
int sum =
QtConcurrent::blockingMappedReduced(list, IntSquare(), intSumReduce, initialValue);
QCOMPARE(sum, 24);
int sum2 = QtConcurrent::blockingMappedReduced(
list.constBegin(), list.constEnd(), IntSquare(), intSumReduce, initialValue);
QCOMPARE(sum2, 24);
int sum3 = QtConcurrent::blockingMappedReduced(
QList<int>(list), IntSquare(), intSumReduce, initialValue);
QCOMPARE(sum3, 24);
}
// function-function
{
int sum = QtConcurrent::blockingMappedReduced(list, intSquare, intSumReduce, initialValue);
QCOMPARE(sum, 24);
int sum2 = QtConcurrent::blockingMappedReduced(
list.constBegin(), list.constEnd(), intSquare, intSumReduce, initialValue);
QCOMPARE(sum2, 24);
int sum3 = QtConcurrent::blockingMappedReduced(
QList<int>(list), intSquare, intSumReduce, initialValue);
QCOMPARE(sum3, 24);
}
auto push_back = static_cast<void (QVector<int>::*)(const int &)>(&QVector<int>::push_back);
QVector<int> initialIntVector;
initialIntVector.push_back(10);
// functor-member
{
QList<int> list2 = QtConcurrent::blockingMappedReduced(
list, IntSquare(), push_back, initialIntVector, OrderedReduce);
QCOMPARE(list, QList<int>() << 1 << 2 << 3);
QCOMPARE(list2, QList<int>() << 10 << 1 << 4 << 9);
QList<int> list3 = QtConcurrent::blockingMappedReduced(list.constBegin(),
list.constEnd(),
IntSquare(),
push_back,
initialIntVector,
OrderedReduce);
QCOMPARE(list, QList<int>() << 1 << 2 << 3);
QCOMPARE(list3, QList<int>() << 10 << 1 << 4 << 9);
QList<int> list4 = QtConcurrent::blockingMappedReduced(
QList<int>(list), IntSquare(), push_back, initialIntVector, OrderedReduce);
QCOMPARE(list, QList<int>() << 1 << 2 << 3);
QCOMPARE(list4, QList<int>() << 10 << 1 << 4 << 9);
}
// member-functor
{
int sum = QtConcurrent::blockingMappedReduced<int>(
numberList, &Number::toInt, IntSumReduce(), initialValue);
QCOMPARE(sum, 16);
int sum2 = QtConcurrent::blockingMappedReduced<int>(numberList.constBegin(),
numberList.constEnd(),
&Number::toInt,
IntSumReduce(),
initialValue);
QCOMPARE(sum2, 16);
int sum3 = QtConcurrent::blockingMappedReduced<int>(
QList<Number>(numberList), &Number::toInt, IntSumReduce(), initialValue);
QCOMPARE(sum3, 16);
}
// member-member
{
QList<int> list2 = QtConcurrent::blockingMappedReduced(
numberList, &Number::toInt, push_back, initialIntVector, OrderedReduce);
QCOMPARE(list2, QList<int>() << 10 << 1 << 2 << 3);
QList<int> list3 = QtConcurrent::blockingMappedReduced(numberList.constBegin(),
numberList.constEnd(),
&Number::toInt,
push_back,
initialIntVector,
OrderedReduce);
QCOMPARE(list3, QList<int>() << 10 << 1 << 2 << 3);
QList<int> list4 = QtConcurrent::blockingMappedReduced(QList<Number>(numberList),
&Number::toInt,
push_back,
initialIntVector,
OrderedReduce);
QCOMPARE(list4, QList<int>() << 10 << 1 << 2 << 3);
}
// function-member
{
QList<int> list2 = QtConcurrent::blockingMappedReduced(
list, intSquare, push_back, initialIntVector, OrderedReduce);
QCOMPARE(list, QList<int>() << 1 << 2 << 3);
QCOMPARE(list2, QList<int>() << 10 << 1 << 4 << 9);
QList<int> list3 = QtConcurrent::blockingMappedReduced(list.constBegin(),
list.constEnd(),
intSquare,
push_back,
initialIntVector,
OrderedReduce);
QCOMPARE(list, QList<int>() << 1 << 2 << 3);
QCOMPARE(list3, QList<int>() << 10 << 1 << 4 << 9);
QList<int> list4 = QtConcurrent::blockingMappedReduced(
QList<int>(list), intSquare, push_back, initialIntVector, OrderedReduce);
QCOMPARE(list, QList<int>() << 1 << 2 << 3);
QCOMPARE(list4, QList<int>() << 10 << 1 << 4 << 9);
}
// member-function
{
int sum = QtConcurrent::blockingMappedReduced(
numberList, &Number::toInt, intSumReduce, initialValue);
QCOMPARE(sum, 16);
int sum2 = QtConcurrent::blockingMappedReduced(numberList.constBegin(),
numberList.constEnd(),
&Number::toInt,
intSumReduce,
initialValue);
QCOMPARE(sum2, 16);
int sum3 = QtConcurrent::blockingMappedReduced(
QList<Number>(numberList), &Number::toInt, intSumReduce, initialValue);
QCOMPARE(sum3, 16);
}
}
QTEST_MAIN(tst_QtConcurrentMap)
#include "tst_qtconcurrentmap.moc"