Revision control
++ // 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
++ // Qt-Security score:significant reason:default
++
++ #ifndef QTCONCURRENT_FILTERKERNEL_H
++ #define QTCONCURRENT_FILTERKERNEL_H
++
++ #include <QtConcurrent/qtconcurrent_global.h>
++
++ #if !defined(QT_NO_CONCURRENT) || defined (Q_QDOC)
++
++ #include <QtConcurrent/qtconcurrentiteratekernel.h>
++ #include <QtConcurrent/qtconcurrentmapkernel.h>
++ #include <QtConcurrent/qtconcurrentreducekernel.h>
++
++ QT_BEGIN_NAMESPACE
++
++
++
++ namespace QtConcurrent {
++
++ template <typename T>
++ struct qValueType
++ {
++ typedef typename T::value_type value_type;
++ };
++
++ template <typename T>
++ struct qValueType<const T*>
++ {
++ typedef T value_type;
++ };
++
++ template <typename T>
++ struct qValueType<T*>
++ {
++ typedef T value_type;
++ };
++
++ // Implementation of filter
++ template <typename Sequence, typename KeepFunctor, typename ReduceFunctor>
++ class FilterKernel : public IterateKernel<typename Sequence::const_iterator, void>
++ {
++ typedef ReduceKernel<ReduceFunctor, Sequence, typename Sequence::value_type> Reducer;
++ typedef IterateKernel<typename Sequence::const_iterator, void> IterateKernelType;
++ typedef void T;
++
++ Sequence reducedResult;
++ Sequence &sequence;
++ KeepFunctor keep;
++ ReduceFunctor reduce;
++ Reducer reducer;
++
++ public:
++ template <typename Keep = KeepFunctor, typename Reduce = ReduceFunctor>
++ FilterKernel(QThreadPool *pool, Sequence &_sequence, Keep &&_keep, Reduce &&_reduce)
++ : IterateKernelType(pool, const_cast<const Sequence &>(_sequence).begin(),
++ const_cast<const Sequence &>(_sequence).end()), reducedResult(),
++ sequence(_sequence),
++ keep(std::forward<Keep>(_keep)),
++ reduce(std::forward<Reduce>(_reduce)),
++ reducer(pool, OrderedReduce)
++ { }
++
++ bool runIteration(typename Sequence::const_iterator it, int index, T *) override
++ {
++ IntermediateResults<typename Sequence::value_type> results;
++ results.begin = index;
++ results.end = index + 1;
++
++ if (std::invoke(keep, *it))
++ results.vector.append(*it);
++
++ reducer.runReduce(reduce, reducedResult, results);
++ return false;
++ }
++
++ bool runIterations(typename Sequence::const_iterator sequenceBeginIterator, int begin, int end, T *) override
++ {
++ IntermediateResults<typename Sequence::value_type> results;
++ results.begin = begin;
++ results.end = end;
++ results.vector.reserve(end - begin);
++
++
++ typename Sequence::const_iterator it = sequenceBeginIterator;
++ std::advance(it, begin);
++ for (int i = begin; i < end; ++i) {
++ if (std::invoke(keep, *it))
++ results.vector.append(*it);
++ std::advance(it, 1);
++ }
++
++ reducer.runReduce(reduce, reducedResult, results);
++ return false;
++ }
++
++ void finish() override
++ {
++ reducer.finish(reduce, reducedResult);
++ sequence = std::move(reducedResult);
++ }
++
++ inline bool shouldThrottleThread() override
++ {
++ return IterateKernelType::shouldThrottleThread() || reducer.shouldThrottle();
++ }
++
++ inline bool shouldStartThread() override
++ {
++ return IterateKernelType::shouldStartThread() && reducer.shouldStartThread();
++ }
++
++ typedef void ReturnType;
++ typedef void ResultType;
++ };
++
++ // Implementation of filter-reduce
++ template <typename ReducedResultType,
++ typename Iterator,
++ typename KeepFunctor,
++ typename ReduceFunctor,
++ typename Reducer = ReduceKernel<ReduceFunctor,
++ ReducedResultType,
++ typename qValueType<Iterator>::value_type> >
++ class FilteredReducedKernel : public IterateKernel<Iterator, ReducedResultType>
++ {
++ 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(this->defaultValue.value),
++ keep(std::forward<Keep>(_keep)),
++ reduce(std::forward<Reduce>(_reduce)),
++ reducer(pool, reduceOption)
++ { }
++
++ template <typename Keep = KeepFunctor, typename Reduce = ReduceFunctor>
++ FilteredReducedKernel(QThreadPool *pool, Iterator begin, Iterator end, Keep &&_keep,
++ Reduce &&_reduce, ReducedResultType &&initialValue,
++ ReduceOptions reduceOption)
++ : 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)
++ {
++ }
++
++ bool runIteration(Iterator it, int index, ReducedResultType *) override
++ {
++ IntermediateResults<typename qValueType<Iterator>::value_type> results;
++ results.begin = index;
++ results.end = index + 1;
++
++ if (std::invoke(keep, *it))
++ results.vector.append(*it);
++
++ reducer.runReduce(reduce, reducedResult, results);
++ return false;
++ }
++
++ bool runIterations(Iterator sequenceBeginIterator, int begin, int end, ReducedResultType *) override
++ {
++ IntermediateResults<typename qValueType<Iterator>::value_type> results;
++ results.begin = begin;
++ results.end = end;
++ results.vector.reserve(end - begin);
++
++ Iterator it = sequenceBeginIterator;
++ std::advance(it, begin);
++ for (int i = begin; i < end; ++i) {
++ if (std::invoke(keep, *it))
++ results.vector.append(*it);
++ std::advance(it, 1);
++ }
++
++ reducer.runReduce(reduce, reducedResult, results);
++ return false;
++ }
++
++ void finish() override
++ {
++ reducer.finish(reduce, reducedResult);
++ }
++
++ inline bool shouldThrottleThread() override
++ {
++ return IterateKernelType::shouldThrottleThread() || reducer.shouldThrottle();
++ }
++
++ inline bool shouldStartThread() override
++ {
++ return IterateKernelType::shouldStartThread() && reducer.shouldStartThread();
++ }
++
++ typedef ReducedResultType ReturnType;
++ typedef ReducedResultType ResultType;
++ ReducedResultType *result() override
++ {
++ return &reducedResult;
++ }
++ };
++
++ // Implementation of filter that reports individual results via QFutureInterface
++ template <typename Iterator, typename KeepFunctor>
++ class FilteredEachKernel : public IterateKernel<Iterator, typename qValueType<Iterator>::value_type>
++ {
++ typedef typename qValueType<Iterator>::value_type T;
++ typedef IterateKernel<Iterator, T> IterateKernelType;
++
++ KeepFunctor keep;
++
++ public:
++ typedef T ReturnType;
++ typedef T ResultType;
++
++ template <typename Keep = KeepFunctor>
++ FilteredEachKernel(QThreadPool *pool, Iterator begin, Iterator end, Keep &&_keep)
++ : IterateKernelType(pool, begin, end), keep(std::forward<Keep>(_keep))
++ { }
++
++ void start() override
++ {
++ if (this->futureInterface)
++ this->futureInterface->setFilterMode(true);
++ IterateKernelType::start();
++ }
++
++ bool runIteration(Iterator it, int index, T *) override
++ {
++ if (std::invoke(keep, *it))
++ this->reportResult(&(*it), index);
++ else
++ this->reportResult(nullptr, index);
++ return false;
++ }
++
++ bool runIterations(Iterator sequenceBeginIterator, int begin, int end, T *) override
++ {
++ const int count = end - begin;
++ IntermediateResults<typename qValueType<Iterator>::value_type> results;
++ results.begin = begin;
++ results.end = end;
++ results.vector.reserve(count);
++
++ Iterator it = sequenceBeginIterator;
++ std::advance(it, begin);
++ for (int i = begin; i < end; ++i) {
++ if (std::invoke(keep, *it))
++ results.vector.append(*it);
++ std::advance(it, 1);
++ }
++
++ this->reportResults(results.vector, begin, count);
++ return false;
++ }
++ };
++
++ //! [QtConcurrent-2]
++ template <typename Iterator, typename KeepFunctor>
++ inline
++ ThreadEngineStarter<typename qValueType<Iterator>::value_type>
++ startFiltered(QThreadPool *pool, Iterator begin, Iterator end, KeepFunctor &&functor)
++ {
++ return startThreadEngine(new FilteredEachKernel<Iterator, std::decay_t<KeepFunctor>>
++ (pool, begin, end, std::forward<KeepFunctor>(functor)));
++ }
++
++ //! [QtConcurrent-3]
++ template <typename Sequence, typename KeepFunctor>
++ inline decltype(auto) startFiltered(QThreadPool *pool, Sequence &&sequence, KeepFunctor &&functor)
++ {
++ using DecayedSequence = std::decay_t<Sequence>;
++ using DecayedFunctor = std::decay_t<KeepFunctor>;
++ using SequenceHolderType = SequenceHolder1<DecayedSequence,
++ FilteredEachKernel<typename DecayedSequence::const_iterator, DecayedFunctor>,
++ DecayedFunctor>;
++ return startThreadEngine(new SequenceHolderType(pool, std::forward<Sequence>(sequence),
++ std::forward<KeepFunctor>(functor)));
++ }
++
++ //! [QtConcurrent-4]
++ template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor>
++ inline ThreadEngineStarter<ResultType> startFilteredReduced(QThreadPool *pool,
++ Sequence &&sequence,
++ MapFunctor &&mapFunctor,
++ ReduceFunctor &&reduceFunctor,
++ ReduceOptions options)
++ {
++ using DecayedSequence = std::decay_t<Sequence>;
++ using DecayedMapFunctor = std::decay_t<MapFunctor>;
++ using DecayedReduceFunctor = std::decay_t<ReduceFunctor>;
++ using Iterator = typename DecayedSequence::const_iterator;
++ using Reducer = ReduceKernel<DecayedReduceFunctor, ResultType,
++ typename qValueType<Iterator>::value_type>;
++ using FilteredReduceType = FilteredReducedKernel<ResultType, Iterator, DecayedMapFunctor,
++ DecayedReduceFunctor, Reducer>;
++ using SequenceHolderType = SequenceHolder2<DecayedSequence, FilteredReduceType,
++ DecayedMapFunctor, DecayedReduceFunctor>;
++ return startThreadEngine(new SequenceHolderType(pool, std::forward<Sequence>(sequence),
++ std::forward<MapFunctor>(mapFunctor),
++ std::forward<ReduceFunctor>(reduceFunctor),
++ options));
++ }
++
++
++ //! [QtConcurrent-5]
++ template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
++ inline ThreadEngineStarter<ResultType> startFilteredReduced(QThreadPool *pool,
++ Iterator begin,
++ Iterator end,
++ MapFunctor &&mapFunctor,
++ ReduceFunctor &&reduceFunctor,
++ ReduceOptions options)
++ {
++ using Reducer = ReduceKernel<std::decay_t<ReduceFunctor>, ResultType,
++ typename qValueType<Iterator>::value_type>;
++ using FilteredReduceType = FilteredReducedKernel<ResultType, Iterator, std::decay_t<MapFunctor>,
++ std::decay_t<ReduceFunctor>, Reducer>;
++ return startThreadEngine(
++ new FilteredReduceType(pool, begin, end, std::forward<MapFunctor>(mapFunctor),
++ std::forward<ReduceFunctor>(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(QThreadPool *pool,
++ Sequence &&sequence,
++ MapFunctor &&mapFunctor,
++ ReduceFunctor &&reduceFunctor,
++ ResultType &&initialValue,
++ ReduceOptions options)
++ {
++ using DecayedSequence = std::decay_t<Sequence>;
++ using DecayedMapFunctor = std::decay_t<MapFunctor>;
++ using DecayedReduceFunctor = std::decay_t<ReduceFunctor>;
++ using Iterator = typename DecayedSequence::const_iterator;
++ using Reducer = ReduceKernel<DecayedReduceFunctor, ResultType,
++ typename qValueType<Iterator>::value_type>;
++ using FilteredReduceType = FilteredReducedKernel<ResultType, Iterator, DecayedMapFunctor,
++ DecayedReduceFunctor, Reducer>;
++ using SequenceHolderType = SequenceHolder2<DecayedSequence, FilteredReduceType,
++ DecayedMapFunctor, DecayedReduceFunctor>;
++ return startThreadEngine(new SequenceHolderType(
++ pool, std::forward<Sequence>(sequence), std::forward<MapFunctor>(mapFunctor),
++ std::forward<ReduceFunctor>(reduceFunctor), std::forward<ResultType>(initialValue),
++ options));
++ }
++
++ //! [QtConcurrent-7]
++ template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
++ inline ThreadEngineStarter<ResultType> startFilteredReduced(QThreadPool *pool,
++ Iterator begin,
++ Iterator end,
++ MapFunctor &&mapFunctor,
++ ReduceFunctor &&reduceFunctor,
++ ResultType &&initialValue,
++ ReduceOptions options)
++ {
++ using Reducer = ReduceKernel<std::decay_t<ReduceFunctor>, ResultType,
++ typename qValueType<Iterator>::value_type>;
++ using FilteredReduceType = FilteredReducedKernel<ResultType, Iterator, std::decay_t<MapFunctor>,
++ std::decay_t<ReduceFunctor>, Reducer>;
++ return startThreadEngine(
++ new FilteredReduceType(pool, begin, end, std::forward<MapFunctor>(mapFunctor),
++ std::forward<ReduceFunctor>(reduceFunctor),
++ std::forward<ResultType>(initialValue), options));
++ }
++
++
++ } // namespace QtConcurrent
++
++
++ QT_END_NAMESPACE
++
++ #endif // QT_NO_CONCURRENT
++
++ #endif