diff options
Diffstat (limited to 'src/concurrent/qtconcurrentiteratekernel.h')
-rw-r--r-- | src/concurrent/qtconcurrentiteratekernel.h | 131 |
1 files changed, 80 insertions, 51 deletions
diff --git a/src/concurrent/qtconcurrentiteratekernel.h b/src/concurrent/qtconcurrentiteratekernel.h index 6caae61816..232f4c8bfe 100644 --- a/src/concurrent/qtconcurrentiteratekernel.h +++ b/src/concurrent/qtconcurrentiteratekernel.h @@ -1,48 +1,12 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtConcurrent module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTCONCURRENT_ITERATEKERNEL_H #define QTCONCURRENT_ITERATEKERNEL_H #include <QtConcurrent/qtconcurrent_global.h> -#if !defined(QT_NO_CONCURRENT) || defined(Q_CLANG_QDOC) +#if !defined(QT_NO_CONCURRENT) || defined(Q_QDOC) #include <QtCore/qatomic.h> #include <QtConcurrent/qtconcurrentmedian.h> @@ -93,23 +57,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.size())); } 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) @@ -122,9 +85,20 @@ public: return vector.data(); } - int currentResultCount; + int currentResultCount = 0; 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 +111,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 +150,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()) ? static_cast<int>(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()) ? static_cast<int>(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()) ? static_cast<int>(std::distance(_begin, _end)) : 0), + forIteration(selectIteration(IteratorCategory())), + progressReportingEnabled(true), + defaultValue(std::forward<U>(_defaultValue)) { } @@ -199,7 +219,7 @@ public: ThreadFunctionResult forThreadFunction() { BlockSizeManager blockSizeManager(ThreadEngineBase::threadPool, iterationCount); - ResultReporter<T> resultReporter(this); + ResultReporter<T> resultReporter = createResultsReporter(); for(;;) { if (this->isCanceled()) @@ -252,7 +272,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 +303,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 +322,7 @@ public: const int iterationCount; const bool forIteration; bool progressReportingEnabled; + DefaultValueContainer<ResultType> defaultValue; }; } // namespace QtConcurrent |