blob: f2c15062c7411d2f4f39e079aecccaeecef79cfe [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QTCONCURRENT_FILTERKERNEL_H
#define QTCONCURRENT_FILTERKERNEL_H
#include <QtConcurrent/qtconcurrent_global.h>
#ifndef QT_NO_CONCURRENT
#include <QtConcurrent/qtconcurrentiteratekernel.h>
#include <QtConcurrent/qtconcurrentmapkernel.h>
#include <QtConcurrent/qtconcurrentreducekernel.h>
QT_BEGIN_NAMESPACE
#ifndef Q_QDOC
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 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<const Sequence &>(_sequence).begin(), const_cast<const Sequence &>(_sequence).end()), reducedResult(),
sequence(_sequence),
keep(_keep),
reduce(_reduce),
reducer(OrderedReduce)
{ }
bool runIteration(typename Sequence::const_iterator it, int index, T *)
{
IntermediateResults<typename Sequence::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(typename Sequence::const_iterator sequenceBeginIterator, int begin, int end, T *)
{
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 (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 <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:
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<typename qValueType<Iterator>::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<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 (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 <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;
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<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 (keep(*it))
results.vector.append(*it);
std::advance(it, 1);
}
this->reportResults(results.vector, begin, count);
return false;
}
};
template <typename Iterator, typename KeepFunctor>
inline
ThreadEngineStarter<typename qValueType<Iterator>::value_type>
startFiltered(Iterator begin, Iterator end, KeepFunctor functor)
{
return startThreadEngine(new FilteredEachKernel<Iterator, KeepFunctor>(begin, end, functor));
}
template <typename Sequence, typename KeepFunctor>
inline ThreadEngineStarter<typename Sequence::value_type>
startFiltered(const Sequence &sequence, KeepFunctor functor)
{
typedef SequenceHolder1<Sequence,
FilteredEachKernel<typename Sequence::const_iterator, KeepFunctor>,
KeepFunctor>
SequenceHolderType;
return startThreadEngine(new SequenceHolderType(sequence, functor));
}
template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor>
inline ThreadEngineStarter<ResultType> startFilteredReduced(const Sequence & sequence,
MapFunctor mapFunctor, ReduceFunctor reduceFunctor,
ReduceOptions options)
{
typedef typename Sequence::const_iterator Iterator;
typedef ReduceKernel<ReduceFunctor, ResultType, typename qValueType<Iterator>::value_type > Reducer;
typedef FilteredReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer> FilteredReduceType;
typedef SequenceHolder2<Sequence, FilteredReduceType, MapFunctor, ReduceFunctor> SequenceHolderType;
return startThreadEngine(new SequenceHolderType(sequence, mapFunctor, reduceFunctor, options));
}
template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
inline ThreadEngineStarter<ResultType> startFilteredReduced(Iterator begin, Iterator end,
MapFunctor mapFunctor, ReduceFunctor reduceFunctor,
ReduceOptions options)
{
typedef ReduceKernel<ReduceFunctor, ResultType, typename qValueType<Iterator>::value_type> Reducer;
typedef FilteredReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer> FilteredReduceType;
return startThreadEngine(new FilteredReduceType(begin, end, mapFunctor, reduceFunctor, options));
}
} // namespace QtConcurrent
#endif // Q_QDOC
QT_END_NAMESPACE
#endif // QT_NO_CONCURRENT
#endif