/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore 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 Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTCONCURRENT_FILTERKERNEL_H #define QTCONCURRENT_FILTERKERNEL_H #include #ifndef QT_NO_CONCURRENT #include #include #include QT_BEGIN_NAMESPACE #ifndef Q_QDOC namespace QtConcurrent { template struct qValueType { typedef typename T::value_type value_type; }; template struct qValueType { typedef T value_type; }; template struct qValueType { typedef T value_type; }; // Implementation of filter template class FilterKernel : public IterateKernel { typedef ReduceKernel Reducer; typedef IterateKernel IterateKernelType; typedef typename ReduceFunctor::result_type T; Sequence reducedResult; Sequence &sequence; KeepFunctor keep; ReduceFunctor reduce; Reducer reducer; public: FilterKernel(Sequence &_sequence, KeepFunctor _keep, ReduceFunctor _reduce) : IterateKernelType(const_cast(_sequence).begin(), const_cast(_sequence).end()), reducedResult(), sequence(_sequence), keep(_keep), reduce(_reduce), reducer(OrderedReduce) { } bool runIteration(typename Sequence::const_iterator it, int index, T *) { IntermediateResults results; results.begin = index; results.end = index + 1; if (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 *) { IntermediateResults 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 (keep(*it)) results.vector.append(*it); std::advance(it, 1); } reducer.runReduce(reduce, reducedResult, results); return false; } void finish() { reducer.finish(reduce, reducedResult); sequence = reducedResult; } inline bool shouldThrottleThread() { return IterateKernelType::shouldThrottleThread() || reducer.shouldThrottle(); } inline bool shouldStartThread() { return IterateKernelType::shouldStartThread() && reducer.shouldStartThread(); } typedef void ReturnType; typedef void ResultType; }; // Implementation of filter-reduce template ::value_type> > class FilteredReducedKernel : public IterateKernel { ReducedResultType reducedResult; KeepFunctor keep; ReduceFunctor reduce; Reducer reducer; typedef IterateKernel IterateKernelType; public: FilteredReducedKernel(Iterator begin, Iterator end, KeepFunctor _keep, ReduceFunctor _reduce, ReduceOptions reduceOption) : IterateKernelType(begin, end), reducedResult(), keep(_keep), reduce(_reduce), reducer(reduceOption) { } #if 0 FilteredReducedKernel(ReducedResultType initialValue, KeepFunctor keep, ReduceFunctor reduce, ReduceOption reduceOption) : reducedResult(initialValue), keep(keep), reduce(reduce), reducer(reduceOption) { } #endif bool runIteration(Iterator it, int index, ReducedResultType *) { IntermediateResults::value_type> results; results.begin = index; results.end = index + 1; if (keep(*it)) results.vector.append(*it); reducer.runReduce(reduce, reducedResult, results); return false; } bool runIterations(Iterator sequenceBeginIterator, int begin, int end, ReducedResultType *) { IntermediateResults::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 (keep(*it)) results.vector.append(*it); std::advance(it, 1); } reducer.runReduce(reduce, reducedResult, results); return false; } void finish() { reducer.finish(reduce, reducedResult); } inline bool shouldThrottleThread() { return IterateKernelType::shouldThrottleThread() || reducer.shouldThrottle(); } inline bool shouldStartThread() { return IterateKernelType::shouldStartThread() && reducer.shouldStartThread(); } typedef ReducedResultType ReturnType; typedef ReducedResultType ResultType; ReducedResultType *result() { return &reducedResult; } }; // Implementation of filter that reports individual results via QFutureInterface template class FilteredEachKernel : public IterateKernel::value_type> { typedef typename qValueType::value_type T; typedef IterateKernel IterateKernelType; KeepFunctor keep; public: typedef T ReturnType; typedef T ResultType; FilteredEachKernel(Iterator begin, Iterator end, KeepFunctor _keep) : IterateKernelType(begin, end), keep(_keep) { } void start() { if (this->futureInterface) this->futureInterface->setFilterMode(true); IterateKernelType::start(); } bool runIteration(Iterator it, int index, T *) { if (keep(*it)) this->reportResult(&(*it), index); else this->reportResult(0, index); return false; } bool runIterations(Iterator sequenceBeginIterator, int begin, int end, T *) { const int count = end - begin; IntermediateResults::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 (keep(*it)) results.vector.append(*it); std::advance(it, 1); } this->reportResults(results.vector, begin, count); return false; } }; template inline ThreadEngineStarter::value_type> startFiltered(Iterator begin, Iterator end, KeepFunctor functor) { return startThreadEngine(new FilteredEachKernel(begin, end, functor)); } template inline ThreadEngineStarter startFiltered(const Sequence &sequence, KeepFunctor functor) { typedef SequenceHolder1, KeepFunctor> SequenceHolderType; return startThreadEngine(new SequenceHolderType(sequence, functor)); } template inline ThreadEngineStarter startFilteredReduced(const Sequence & sequence, MapFunctor mapFunctor, ReduceFunctor reduceFunctor, ReduceOptions options) { typedef typename Sequence::const_iterator Iterator; typedef ReduceKernel::value_type > Reducer; typedef FilteredReducedKernel FilteredReduceType; typedef SequenceHolder2 SequenceHolderType; return startThreadEngine(new SequenceHolderType(sequence, mapFunctor, reduceFunctor, options)); } template inline ThreadEngineStarter startFilteredReduced(Iterator begin, Iterator end, MapFunctor mapFunctor, ReduceFunctor reduceFunctor, ReduceOptions options) { typedef ReduceKernel::value_type> Reducer; typedef FilteredReducedKernel FilteredReduceType; return startThreadEngine(new FilteredReduceType(begin, end, mapFunctor, reduceFunctor, options)); } } // namespace QtConcurrent #endif // Q_QDOC QT_END_NAMESPACE #endif // QT_NO_CONCURRENT #endif