diff options
author | Mårten Nordheim <marten.nordheim@qt.io> | 2020-02-26 18:06:49 +0100 |
---|---|---|
committer | Mårten Nordheim <marten.nordheim@qt.io> | 2020-03-04 17:40:45 +0100 |
commit | d57adfe5f375121c3e233465526ee5d9df03e1e9 (patch) | |
tree | ecf9892b6e7a954f145ef74743caa932033b5253 /src/concurrent | |
parent | d50b22e75df0e0fcecf987813b873e717a225e66 (diff) |
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>
Diffstat (limited to 'src/concurrent')
-rw-r--r-- | src/concurrent/qtconcurrentfilter.cpp | 100 | ||||
-rw-r--r-- | src/concurrent/qtconcurrentfilter.h | 119 | ||||
-rw-r--r-- | src/concurrent/qtconcurrentfilterkernel.h | 44 | ||||
-rw-r--r-- | src/concurrent/qtconcurrentmap.cpp | 81 | ||||
-rw-r--r-- | src/concurrent/qtconcurrentmap.h | 132 | ||||
-rw-r--r-- | src/concurrent/qtconcurrentmapkernel.h | 49 | ||||
-rw-r--r-- | src/concurrent/qtconcurrentreducekernel.h | 10 |
7 files changed, 521 insertions, 14 deletions
diff --git a/src/concurrent/qtconcurrentfilter.cpp b/src/concurrent/qtconcurrentfilter.cpp index 606a9dbe03..bac8ac59fc 100644 --- a/src/concurrent/qtconcurrentfilter.cpp +++ b/src/concurrent/qtconcurrentfilter.cpp @@ -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: @@ -267,6 +267,27 @@ */ /*! + \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) Calls \a filterFunction once for each item from \a begin to \a end. If @@ -285,6 +306,27 @@ */ /*! + \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) Calls \a filterFunction once for each item in \a sequence. If @@ -344,6 +386,29 @@ */ /*! + \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) Calls \a filterFunction once for each item from \a begin to \a end. If @@ -365,6 +430,30 @@ */ /*! + \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 +*/ diff --git a/src/concurrent/qtconcurrentfilter.h b/src/concurrent/qtconcurrentfilter.h index d01b351ad0..4c7d1ee7e5 100644 --- a/src/concurrent/qtconcurrentfilter.h +++ b/src/concurrent/qtconcurrentfilter.h @@ -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 diff --git a/src/concurrent/qtconcurrentfilterkernel.h b/src/concurrent/qtconcurrentfilterkernel.h index e921a3d51a..8ec551eeb2 100644 --- a/src/concurrent/qtconcurrentfilterkernel.h +++ b/src/concurrent/qtconcurrentfilterkernel.h @@ -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 diff --git a/src/concurrent/qtconcurrentmap.cpp b/src/concurrent/qtconcurrentmap.cpp index 157ea14b32..eff381c567 100644 --- a/src/concurrent/qtconcurrentmap.cpp +++ b/src/concurrent/qtconcurrentmap.cpp @@ -119,6 +119,16 @@ */ /*! + \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 function are passed to the reduce function. @@ -344,6 +354,22 @@ */ /*! + \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) Calls \a mapFunction once for each item from \a begin to \a end. The return @@ -359,6 +385,24 @@ */ /*! + \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) Calls \a function once for each item in \a sequence. The \a function is @@ -427,6 +471,24 @@ */ /*! + \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) Calls \a mapFunction once for each item from \a begin to \a end. The return @@ -443,6 +505,25 @@ */ /*! + \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 \internal diff --git a/src/concurrent/qtconcurrentmap.h b/src/concurrent/qtconcurrentmap.h index 151f03cf56..a1e7cf1044 100644 --- a/src/concurrent/qtconcurrentmap.h +++ b/src/concurrent/qtconcurrentmap.h @@ -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) diff --git a/src/concurrent/qtconcurrentmapkernel.h b/src/concurrent/qtconcurrentmapkernel.h index 7c9538a015..3de275a192 100644 --- a/src/concurrent/qtconcurrentmapkernel.h +++ b/src/concurrent/qtconcurrentmapkernel.h @@ -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 diff --git a/src/concurrent/qtconcurrentreducekernel.h b/src/concurrent/qtconcurrentreducekernel.h index 8f9a938952..eabc432374 100644 --- a/src/concurrent/qtconcurrentreducekernel.h +++ b/src/concurrent/qtconcurrentreducekernel.h @@ -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 |