diff options
author | Ivan Solovev <ivan.solovev@qt.io> | 2020-12-01 19:22:16 +0100 |
---|---|---|
committer | Ivan Solovev <ivan.solovev@qt.io> | 2020-12-04 15:36:50 +0100 |
commit | 3d780c0d7068a6a6876d058314b1970810008c1f (patch) | |
tree | 86f3abfbdb95e0f414ebb1d7757108631652ca39 /src/concurrent | |
parent | 0c19e3f703a7c3fd59e6db8a9d4ac7091674b552 (diff) |
QtConcurrent: filter/map reduction without default ctor
Previously a default constructor was required for the result type
of mappedReduced() and filteredReduced(), even if a default value
was provided.
This patch fixes the problem.
The issue was in the ResultReporter type, that was calling
QList::resize() to adjust the size of expected reported results.
A default-value parameter was added to the class, so that
a corresponding overload of QList::resize could be invoked.
Task-number: QTBUG-88452
Change-Id: I51113753e314d76aa74d201b5a7e327a6ca75f47
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
Diffstat (limited to 'src/concurrent')
-rw-r--r-- | src/concurrent/qtconcurrentfilterkernel.h | 20 | ||||
-rw-r--r-- | src/concurrent/qtconcurrentiteratekernel.h | 87 | ||||
-rw-r--r-- | src/concurrent/qtconcurrentmapkernel.h | 26 |
3 files changed, 99 insertions, 34 deletions
diff --git a/src/concurrent/qtconcurrentfilterkernel.h b/src/concurrent/qtconcurrentfilterkernel.h index ede775e9bd..379ea5a946 100644 --- a/src/concurrent/qtconcurrentfilterkernel.h +++ b/src/concurrent/qtconcurrentfilterkernel.h @@ -160,21 +160,19 @@ template <typename ReducedResultType, typename qValueType<Iterator>::value_type> > class FilteredReducedKernel : public IterateKernel<Iterator, ReducedResultType> { - ReducedResultType reducedResult; + ReducedResultType &reducedResult; KeepFunctor keep; ReduceFunctor reduce; Reducer reducer; typedef IterateKernel<Iterator, ReducedResultType> IterateKernelType; public: - template <typename Keep = KeepFunctor, typename Reduce = ReduceFunctor> - FilteredReducedKernel(QThreadPool *pool, - Iterator begin, - Iterator end, - Keep &&_keep, - Reduce &&_reduce, - ReduceOptions reduceOption) - : IterateKernelType(pool, begin, end), reducedResult(), keep(std::forward<Keep>(_keep)), + template<typename Keep = KeepFunctor, typename Reduce = ReduceFunctor> + FilteredReducedKernel(QThreadPool *pool, Iterator begin, Iterator end, Keep &&_keep, + Reduce &&_reduce, ReduceOptions reduceOption) + : IterateKernelType(pool, begin, end), + reducedResult(this->defaultValue.value), + keep(std::forward<Keep>(_keep)), reduce(std::forward<Reduce>(_reduce)), reducer(pool, reduceOption) { } @@ -183,8 +181,8 @@ public: FilteredReducedKernel(QThreadPool *pool, Iterator begin, Iterator end, Keep &&_keep, Reduce &&_reduce, ReducedResultType &&initialValue, ReduceOptions reduceOption) - : IterateKernelType(pool, begin, end), - reducedResult(std::forward<ReducedResultType>(initialValue)), + : IterateKernelType(pool, begin, end, std::forward<ReducedResultType>(initialValue)), + reducedResult(this->defaultValue.value), keep(std::forward<Keep>(_keep)), reduce(std::forward<Reduce>(_reduce)), reducer(pool, reduceOption) diff --git a/src/concurrent/qtconcurrentiteratekernel.h b/src/concurrent/qtconcurrentiteratekernel.h index 6caae61816..30033e9c66 100644 --- a/src/concurrent/qtconcurrentiteratekernel.h +++ b/src/concurrent/qtconcurrentiteratekernel.h @@ -93,23 +93,22 @@ template <typename T> class ResultReporter { public: - ResultReporter(ThreadEngine<T> *_threadEngine) - :threadEngine(_threadEngine) + ResultReporter(ThreadEngine<T> *_threadEngine, T &_defaultValue) + : threadEngine(_threadEngine), defaultValue(_defaultValue) { - } void reserveSpace(int resultCount) { currentResultCount = resultCount; - vector.resize(qMax(resultCount, vector.count())); + resizeList(qMax(resultCount, vector.count())); } void reportResults(int begin) { const int useVectorThreshold = 4; // Tunable parameter. if (currentResultCount > useVectorThreshold) { - vector.resize(currentResultCount); + resizeList(currentResultCount); threadEngine->reportResults(vector, begin); } else { for (int i = 0; i < currentResultCount; ++i) @@ -125,6 +124,17 @@ public: int currentResultCount; ThreadEngine<T> *threadEngine; QList<T> vector; + +private: + void resizeList(qsizetype size) + { + if constexpr (std::is_default_constructible_v<T>) + vector.resize(size); + else + vector.resize(size, defaultValue); + } + + T &defaultValue; }; template <> @@ -137,6 +147,22 @@ public: inline void * getPointer() { return nullptr; } }; +template<typename T> +struct DefaultValueContainer +{ + template<typename U = T> + DefaultValueContainer(U &&_value) : value(std::forward<U>(_value)) + { + } + + T value; +}; + +template<> +struct DefaultValueContainer<void> +{ +}; + inline bool selectIteration(std::bidirectional_iterator_tag) { return false; // while @@ -160,11 +186,41 @@ class IterateKernel : public ThreadEngine<T> public: typedef T ResultType; + template<typename U = T, std::enable_if_t<std::is_same_v<U, void>, bool> = true> + IterateKernel(QThreadPool *pool, Iterator _begin, Iterator _end) + : ThreadEngine<U>(pool), + begin(_begin), + end(_end), + current(_begin), + iterationCount(selectIteration(IteratorCategory()) ? std::distance(_begin, _end) : 0), + forIteration(selectIteration(IteratorCategory())), + progressReportingEnabled(true) + { + } + + template<typename U = T, std::enable_if_t<!std::is_same_v<U, void>, bool> = true> IterateKernel(QThreadPool *pool, Iterator _begin, Iterator _end) - : ThreadEngine<T>(pool), begin(_begin), end(_end), current(_begin) - , iterationCount(selectIteration(IteratorCategory()) ? std::distance(_begin, _end) : 0) - , forIteration(selectIteration(IteratorCategory())) - , progressReportingEnabled(true) + : ThreadEngine<U>(pool), + begin(_begin), + end(_end), + current(_begin), + iterationCount(selectIteration(IteratorCategory()) ? std::distance(_begin, _end) : 0), + forIteration(selectIteration(IteratorCategory())), + progressReportingEnabled(true), + defaultValue(U()) + { + } + + template<typename U = T, std::enable_if_t<!std::is_same_v<U, void>, bool> = true> + IterateKernel(QThreadPool *pool, Iterator _begin, Iterator _end, U &&_defaultValue) + : ThreadEngine<U>(pool), + begin(_begin), + end(_end), + current(_begin), + iterationCount(selectIteration(IteratorCategory()) ? std::distance(_begin, _end) : 0), + forIteration(selectIteration(IteratorCategory())), + progressReportingEnabled(true), + defaultValue(std::forward<U>(_defaultValue)) { } @@ -199,7 +255,7 @@ public: ThreadFunctionResult forThreadFunction() { BlockSizeManager blockSizeManager(ThreadEngineBase::threadPool, iterationCount); - ResultReporter<T> resultReporter(this); + ResultReporter<T> resultReporter = createResultsReporter(); for(;;) { if (this->isCanceled()) @@ -252,7 +308,7 @@ public: if (iteratorThreads.testAndSetAcquire(0, 1) == false) return ThreadFinished; - ResultReporter<T> resultReporter(this); + ResultReporter<T> resultReporter = createResultsReporter(); resultReporter.reserveSpace(1); while (current != end) { @@ -283,6 +339,14 @@ public: return ThreadFinished; } +private: + ResultReporter<T> createResultsReporter() + { + if constexpr (!std::is_same_v<T, void>) + return ResultReporter<T>(this, defaultValue.value); + else + return ResultReporter<T>(this); + } public: const Iterator begin; @@ -294,6 +358,7 @@ public: const int iterationCount; const bool forIteration; bool progressReportingEnabled; + DefaultValueContainer<ResultType> defaultValue; }; } // namespace QtConcurrent diff --git a/src/concurrent/qtconcurrentmapkernel.h b/src/concurrent/qtconcurrentmapkernel.h index 2753bc7d0a..62e4c0b5dd 100644 --- a/src/concurrent/qtconcurrentmapkernel.h +++ b/src/concurrent/qtconcurrentmapkernel.h @@ -93,7 +93,7 @@ template <typename ReducedResultType, QtPrivate::MapResultType<Iterator, MapFunctor>>> class MappedReducedKernel : public IterateKernel<Iterator, ReducedResultType> { - ReducedResultType reducedResult; + ReducedResultType &reducedResult; MapFunctor map; ReduceFunctor reduce; Reducer reducer; @@ -102,20 +102,22 @@ class MappedReducedKernel : public IterateKernel<Iterator, ReducedResultType> public: typedef ReducedResultType ReturnType; - template <typename F1 = MapFunctor, typename F2 = ReduceFunctor> - MappedReducedKernel(QThreadPool *pool, Iterator begin, Iterator end, F1 &&_map, - F2 &&_reduce, ReduceOptions reduceOptions) - : IterateKernel<Iterator, ReducedResultType>(pool, begin, end), reducedResult(), - map(std::forward<F1>(_map)), reduce(std::forward<F2>(_reduce)), + template<typename F1 = MapFunctor, typename F2 = ReduceFunctor> + MappedReducedKernel(QThreadPool *pool, Iterator begin, Iterator end, F1 &&_map, F2 &&_reduce, + ReduceOptions reduceOptions) + : IterateKernel<Iterator, ReducedResultType>(pool, begin, end), + reducedResult(this->defaultValue.value), + map(std::forward<F1>(_map)), + reduce(std::forward<F2>(_reduce)), reducer(pool, reduceOptions) { } - template <typename F1 = MapFunctor, typename F2 = ReduceFunctor> - MappedReducedKernel(QThreadPool *pool, Iterator begin, Iterator end, F1 &&_map, - F2 &&_reduce, ReducedResultType &&initialValue, - ReduceOptions reduceOptions) - : IterateKernel<Iterator, ReducedResultType>(pool, begin, end), - reducedResult(std::forward<ReducedResultType>(initialValue)), + template<typename F1 = MapFunctor, typename F2 = ReduceFunctor> + MappedReducedKernel(QThreadPool *pool, Iterator begin, Iterator end, F1 &&_map, F2 &&_reduce, + ReducedResultType &&initialValue, ReduceOptions reduceOptions) + : IterateKernel<Iterator, ReducedResultType>(pool, begin, end, + std::forward<ReducedResultType>(initialValue)), + reducedResult(this->defaultValue.value), map(std::forward<F1>(_map)), reduce(std::forward<F2>(_reduce)), reducer(pool, reduceOptions) |