diff --git a/src/concurrent/qtconcurrentfilterkernel.h b/src/concurrent/qtconcurrentfilterkernel.h index ede775e9bd9..379ea5a946c 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 6caae618163..30033e9c664 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) + : 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), + 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 2753bc7d0a0..62e4c0b5dde 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) diff --git a/tests/auto/concurrent/qtconcurrentfiltermapgenerated/tst_qtconcurrent_selected_tests.cpp b/tests/auto/concurrent/qtconcurrentfiltermapgenerated/tst_qtconcurrent_selected_tests.cpp index ebe6dba70ef..6b726487209 100644 --- a/tests/auto/concurrent/qtconcurrentfiltermapgenerated/tst_qtconcurrent_selected_tests.cpp +++ b/tests/auto/concurrent/qtconcurrentfiltermapgenerated/tst_qtconcurrent_selected_tests.cpp @@ -294,3 +294,79 @@ void tst_QtConcurrentFilterMapGenerated::moveOnlyReductionItem() QCOMPARE(result, expected_result);*/ } + +void tst_QtConcurrentFilterMapGenerated::noDefaultConstructorItemMapped() +{ + /* test for + template ResultType blockingMappedReduced(QThreadPool* pool, + const Sequence & sequence, MapFunctor function, ReduceFunctor reduceFunction, reductionitemtype + && initialValue, ReduceOptions); + + with + inputsequence=standard + inputsequencepassing=lvalue + inputitemtype=standard + maptype=same + mappeditemtype=standard + reductiontype=different + reductionitemtype=noconstruct + mapfunction=functor + mapfunctionpassing=lvalue + reductionfunction=function + reductionfunctionpassing=lvalue + reductioninitialvaluepassing=lvalue + reductionoptions=unspecified + */ + + QThreadPool pool; + pool.setMaxThreadCount(1); + auto input_sequence = []() { + std::vector> result; + result.push_back(SequenceItem(1, true)); + result.push_back(SequenceItem(2, true)); + result.push_back(SequenceItem(3, true)); + result.push_back(SequenceItem(4, true)); + result.push_back(SequenceItem(5, true)); + result.push_back(SequenceItem(6, true)); + return result; + }(); + + auto map = MyMap, SequenceItem> {}; + auto reductor = myReduce, NoConstructSequenceItem>; + auto initialvalue = NoConstructSequenceItem(0, true); + + auto result = + QtConcurrent::blockingMappedReduced(&pool, input_sequence, map, reductor, initialvalue); + + auto expected_result = NoConstructSequenceItem(42, true); + + QCOMPARE(result, expected_result); +} + +void tst_QtConcurrentFilterMapGenerated::noDefaultConstructorItemFiltered() +{ + QThreadPool pool; + pool.setMaxThreadCount(1); + auto input_sequence = []() { + std::vector> result; + result.push_back(SequenceItem(1, true)); + result.push_back(SequenceItem(2, true)); + result.push_back(SequenceItem(3, true)); + result.push_back(SequenceItem(4, true)); + result.push_back(SequenceItem(5, true)); + result.push_back(SequenceItem(6, true)); + return result; + }(); + + auto filter = MyFilter> {}; + auto reductor = myReduce, NoConstructSequenceItem>; + auto initialvalue = NoConstructSequenceItem(0, true); + + auto result = QtConcurrent::blockingFilteredReduced(&pool, input_sequence, filter, reductor, + initialvalue); + + auto expected_result = NoConstructSequenceItem(9, true); + + QCOMPARE(result, expected_result); +} diff --git a/tests/auto/concurrent/qtconcurrentfiltermapgenerated/tst_qtconcurrentfiltermapgenerated.h b/tests/auto/concurrent/qtconcurrentfiltermapgenerated/tst_qtconcurrentfiltermapgenerated.h index 9a32f534996..e6229236a33 100644 --- a/tests/auto/concurrent/qtconcurrentfiltermapgenerated/tst_qtconcurrentfiltermapgenerated.h +++ b/tests/auto/concurrent/qtconcurrentfiltermapgenerated/tst_qtconcurrentfiltermapgenerated.h @@ -44,6 +44,8 @@ private slots: void moveOnlyReduceObject(); void functorAsReduction(); void moveOnlyReductionItem(); + void noDefaultConstructorItemMapped(); + void noDefaultConstructorItemFiltered(); // START_GENERATED_SLOTS (see generate_tests.py) void test1(); // END_GENERATED_SLOTS (see generate_tests.py)