From 3d780c0d7068a6a6876d058314b1970810008c1f Mon Sep 17 00:00:00 2001 From: Ivan Solovev Date: Tue, 1 Dec 2020 19:22:16 +0100 Subject: 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 --- src/concurrent/qtconcurrentfilterkernel.h | 20 ++++--- src/concurrent/qtconcurrentiteratekernel.h | 87 ++++++++++++++++++++++++++---- src/concurrent/qtconcurrentmapkernel.h | 26 ++++----- 3 files changed, 99 insertions(+), 34 deletions(-) (limited to 'src/concurrent') 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 ::value_type> > class FilteredReducedKernel : public IterateKernel { - ReducedResultType reducedResult; + ReducedResultType &reducedResult; KeepFunctor keep; ReduceFunctor reduce; Reducer reducer; typedef IterateKernel IterateKernelType; public: - template - FilteredReducedKernel(QThreadPool *pool, - Iterator begin, - Iterator end, - Keep &&_keep, - Reduce &&_reduce, - ReduceOptions reduceOption) - : IterateKernelType(pool, begin, end), reducedResult(), keep(std::forward(_keep)), + template + 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)), reduce(std::forward(_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(initialValue)), + : IterateKernelType(pool, begin, end, std::forward(initialValue)), + reducedResult(this->defaultValue.value), keep(std::forward(_keep)), reduce(std::forward(_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 class ResultReporter { public: - ResultReporter(ThreadEngine *_threadEngine) - :threadEngine(_threadEngine) + ResultReporter(ThreadEngine *_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 *threadEngine; QList vector; + +private: + void resizeList(qsizetype size) + { + if constexpr (std::is_default_constructible_v) + vector.resize(size); + else + vector.resize(size, defaultValue); + } + + T &defaultValue; }; template <> @@ -137,6 +147,22 @@ public: inline void * getPointer() { return nullptr; } }; +template +struct DefaultValueContainer +{ + template + DefaultValueContainer(U &&_value) : value(std::forward(_value)) + { + } + + T value; +}; + +template<> +struct DefaultValueContainer +{ +}; + inline bool selectIteration(std::bidirectional_iterator_tag) { return false; // while @@ -160,11 +186,41 @@ class IterateKernel : public ThreadEngine public: typedef T ResultType; + template, bool> = true> + IterateKernel(QThreadPool *pool, Iterator _begin, Iterator _end) + : ThreadEngine(pool), + begin(_begin), + end(_end), + current(_begin), + iterationCount(selectIteration(IteratorCategory()) ? std::distance(_begin, _end) : 0), + forIteration(selectIteration(IteratorCategory())), + progressReportingEnabled(true) + { + } + + template, bool> = true> IterateKernel(QThreadPool *pool, Iterator _begin, Iterator _end) - : ThreadEngine(pool), begin(_begin), end(_end), current(_begin) - , iterationCount(selectIteration(IteratorCategory()) ? std::distance(_begin, _end) : 0) - , forIteration(selectIteration(IteratorCategory())) - , progressReportingEnabled(true) + : ThreadEngine(pool), + begin(_begin), + end(_end), + current(_begin), + iterationCount(selectIteration(IteratorCategory()) ? std::distance(_begin, _end) : 0), + forIteration(selectIteration(IteratorCategory())), + progressReportingEnabled(true), + defaultValue(U()) + { + } + + template, bool> = true> + IterateKernel(QThreadPool *pool, Iterator _begin, Iterator _end, U &&_defaultValue) + : ThreadEngine(pool), + begin(_begin), + end(_end), + current(_begin), + iterationCount(selectIteration(IteratorCategory()) ? std::distance(_begin, _end) : 0), + forIteration(selectIteration(IteratorCategory())), + progressReportingEnabled(true), + defaultValue(std::forward(_defaultValue)) { } @@ -199,7 +255,7 @@ public: ThreadFunctionResult forThreadFunction() { BlockSizeManager blockSizeManager(ThreadEngineBase::threadPool, iterationCount); - ResultReporter resultReporter(this); + ResultReporter resultReporter = createResultsReporter(); for(;;) { if (this->isCanceled()) @@ -252,7 +308,7 @@ public: if (iteratorThreads.testAndSetAcquire(0, 1) == false) return ThreadFinished; - ResultReporter resultReporter(this); + ResultReporter resultReporter = createResultsReporter(); resultReporter.reserveSpace(1); while (current != end) { @@ -283,6 +339,14 @@ public: return ThreadFinished; } +private: + ResultReporter createResultsReporter() + { + if constexpr (!std::is_same_v) + return ResultReporter(this, defaultValue.value); + else + return ResultReporter(this); + } public: const Iterator begin; @@ -294,6 +358,7 @@ public: const int iterationCount; const bool forIteration; bool progressReportingEnabled; + DefaultValueContainer 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 >> class MappedReducedKernel : public IterateKernel { - ReducedResultType reducedResult; + ReducedResultType &reducedResult; MapFunctor map; ReduceFunctor reduce; Reducer reducer; @@ -102,20 +102,22 @@ class MappedReducedKernel : public IterateKernel public: typedef ReducedResultType ReturnType; - template - MappedReducedKernel(QThreadPool *pool, Iterator begin, Iterator end, F1 &&_map, - F2 &&_reduce, ReduceOptions reduceOptions) - : IterateKernel(pool, begin, end), reducedResult(), - map(std::forward(_map)), reduce(std::forward(_reduce)), + template + MappedReducedKernel(QThreadPool *pool, Iterator begin, Iterator end, F1 &&_map, F2 &&_reduce, + ReduceOptions reduceOptions) + : IterateKernel(pool, begin, end), + reducedResult(this->defaultValue.value), + map(std::forward(_map)), + reduce(std::forward(_reduce)), reducer(pool, reduceOptions) { } - template - MappedReducedKernel(QThreadPool *pool, Iterator begin, Iterator end, F1 &&_map, - F2 &&_reduce, ReducedResultType &&initialValue, - ReduceOptions reduceOptions) - : IterateKernel(pool, begin, end), - reducedResult(std::forward(initialValue)), + template + MappedReducedKernel(QThreadPool *pool, Iterator begin, Iterator end, F1 &&_map, F2 &&_reduce, + ReducedResultType &&initialValue, ReduceOptions reduceOptions) + : IterateKernel(pool, begin, end, + std::forward(initialValue)), + reducedResult(this->defaultValue.value), map(std::forward(_map)), reduce(std::forward(_reduce)), reducer(pool, reduceOptions) -- cgit v1.2.3