qtconcurrentfilterkernel.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
00004 ** All rights reserved.
00005 ** Contact: Nokia Corporation (qt-info@nokia.com)
00006 **
00007 ** This file is part of the QtCore module of the Qt Toolkit.
00008 **
00009 ** $QT_BEGIN_LICENSE:LGPL$
00010 ** Commercial Usage
00011 ** Licensees holding valid Qt Commercial licenses may use this file in
00012 ** accordance with the Qt Commercial License Agreement provided with the
00013 ** Software or, alternatively, in accordance with the terms contained in
00014 ** a written agreement between you and Nokia.
00015 **
00016 ** GNU Lesser General Public License Usage
00017 ** Alternatively, this file may be used under the terms of the GNU Lesser
00018 ** General Public License version 2.1 as published by the Free Software
00019 ** Foundation and appearing in the file LICENSE.LGPL included in the
00020 ** packaging of this file.  Please review the following information to
00021 ** ensure the GNU Lesser General Public License version 2.1 requirements
00022 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
00023 **
00024 ** In addition, as a special exception, Nokia gives you certain additional
00025 ** rights.  These rights are described in the Nokia Qt LGPL Exception
00026 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this module.
00027 **
00028 ** GNU General Public License Usage
00029 ** Alternatively, this file may be used under the terms of the GNU
00030 ** General Public License version 3.0 as published by the Free Software
00031 ** Foundation and appearing in the file LICENSE.GPL included in the
00032 ** packaging of this file.  Please review the following information to
00033 ** ensure the GNU General Public License version 3.0 requirements will be
00034 ** met: http://www.gnu.org/copyleft/gpl.html.
00035 **
00036 ** If you have questions regarding the use of this file, please contact
00037 ** Nokia at qt-info@nokia.com.
00038 ** $QT_END_LICENSE$
00039 **
00040 ****************************************************************************/
00041 
00042 #ifndef QTCONCURRENT_FILTERKERNEL_H
00043 #define QTCONCURRENT_FILTERKERNEL_H
00044 
00045 #include <QtCore/qglobal.h>
00046 
00047 #ifndef QT_NO_CONCURRENT
00048 
00049 #include <QtCore/qtconcurrentiteratekernel.h>
00050 #include <QtCore/qtconcurrentmapkernel.h>
00051 #include <QtCore/qtconcurrentreducekernel.h>
00052 
00053 QT_BEGIN_HEADER
00054 QT_BEGIN_NAMESPACE
00055 
00056 QT_MODULE(Core)
00057 
00058 #ifndef qdoc
00059 
00060 namespace QtConcurrent {
00061 
00062 template <typename T>
00063 struct qValueType
00064 {
00065     typedef typename T::value_type value_type;
00066 };
00067 
00068 template <typename T>
00069 struct qValueType<const T*>
00070 {
00071     typedef T value_type;
00072 };
00073 
00074 template <typename T>
00075 struct qValueType<T*>
00076 {
00077     typedef T value_type;
00078 };
00079 
00080 // Implementation of filter
00081 template <typename Sequence, typename KeepFunctor, typename ReduceFunctor>
00082 class FilterKernel : public IterateKernel<typename Sequence::const_iterator, void>
00083 {
00084     typedef ReduceKernel<ReduceFunctor, Sequence, typename Sequence::value_type> Reducer;
00085     typedef IterateKernel<typename Sequence::const_iterator, void> IterateKernelType;
00086     typedef typename ReduceFunctor::result_type T;
00087 
00088     Sequence reducedResult;
00089     Sequence &sequence;
00090     KeepFunctor keep;
00091     ReduceFunctor reduce;
00092     Reducer reducer;
00093 
00094 public:
00095     FilterKernel(Sequence &_sequence, KeepFunctor _keep, ReduceFunctor _reduce)
00096         : IterateKernelType(const_cast<const Sequence &>(_sequence).begin(), const_cast<const Sequence &>(_sequence).end()), reducedResult(),
00097           sequence(_sequence),
00098           keep(_keep),
00099           reduce(_reduce),
00100           reducer(OrderedReduce)
00101     { }
00102 
00103     bool runIteration(typename Sequence::const_iterator it, int index, T *)
00104     {
00105         IntermediateResults<typename Sequence::value_type> results;
00106         results.begin = index;
00107         results.end = index + 1;
00108 
00109             if (keep(*it))
00110                 results.vector.append(*it);
00111 
00112             reducer.runReduce(reduce, reducedResult, results);
00113             return false;
00114     }
00115 
00116     bool runIterations(typename Sequence::const_iterator sequenceBeginIterator, int begin, int end, T *)
00117     {
00118         IntermediateResults<typename Sequence::value_type> results;
00119         results.begin = begin;
00120         results.end = end;
00121         results.vector.reserve(end - begin);
00122 
00123 
00124         typename Sequence::const_iterator it = sequenceBeginIterator;
00125         advance(it, begin);
00126         for (int i = begin; i < end; ++i) {
00127             if (keep(*it))
00128                 results.vector.append(*it);
00129             advance(it, 1);
00130         }
00131 
00132         reducer.runReduce(reduce, reducedResult, results);
00133         return false;
00134     }
00135 
00136     void finish()
00137     {
00138         reducer.finish(reduce, reducedResult);
00139         sequence = reducedResult;
00140     }
00141 
00142     inline bool shouldThrottleThread()
00143     {
00144         return IterateKernelType::shouldThrottleThread() || reducer.shouldThrottle();
00145     }
00146 
00147     inline bool shouldStartThread()
00148     {
00149         return IterateKernelType::shouldStartThread() && reducer.shouldStartThread();
00150     }
00151 
00152     typedef void ReturnType;
00153     typedef void ResultType;
00154 };
00155 
00156 // Implementation of filter-reduce
00157 template <typename ReducedResultType,
00158           typename Iterator,
00159           typename KeepFunctor,
00160           typename ReduceFunctor,
00161           typename Reducer = ReduceKernel<ReduceFunctor,
00162                                           ReducedResultType,
00163                                           typename qValueType<Iterator>::value_type> >
00164 class FilteredReducedKernel : public IterateKernel<Iterator, ReducedResultType>
00165 {
00166     ReducedResultType reducedResult;
00167     KeepFunctor keep;
00168     ReduceFunctor reduce;
00169     Reducer reducer;
00170     typedef IterateKernel<Iterator, ReducedResultType> IterateKernelType;
00171 
00172 public:
00173     FilteredReducedKernel(Iterator begin,
00174                           Iterator end,
00175                           KeepFunctor _keep,
00176                           ReduceFunctor _reduce,
00177                           ReduceOptions reduceOption)
00178         : IterateKernelType(begin, end), reducedResult(), keep(_keep), reduce(_reduce), reducer(reduceOption)
00179     { }
00180 
00181 #if 0
00182     FilteredReducedKernel(ReducedResultType initialValue,
00183                           KeepFunctor keep,
00184                           ReduceFunctor reduce,
00185                           ReduceOption reduceOption)
00186         : reducedResult(initialValue), keep(keep), reduce(reduce), reducer(reduceOption)
00187     { }
00188 #endif
00189 
00190     bool runIteration(Iterator it, int index, ReducedResultType *)
00191     {
00192         IntermediateResults<typename qValueType<Iterator>::value_type> results;
00193         results.begin = index;
00194         results.end = index + 1;
00195 
00196         if (keep(*it))
00197             results.vector.append(*it);
00198 
00199         reducer.runReduce(reduce, reducedResult, results);
00200         return false;
00201     }
00202 
00203     bool runIterations(Iterator sequenceBeginIterator, int begin, int end, ReducedResultType *)
00204     {
00205         IntermediateResults<typename qValueType<Iterator>::value_type> results;
00206         results.begin = begin;
00207         results.end = end;
00208         results.vector.reserve(end - begin);
00209 
00210         Iterator it = sequenceBeginIterator;
00211         advance(it, begin);
00212         for (int i = begin; i < end; ++i) {
00213             if (keep(*it))
00214                 results.vector.append(*it);
00215             advance(it, 1);
00216         }
00217 
00218         reducer.runReduce(reduce, reducedResult, results);
00219         return false;
00220     }
00221 
00222     void finish()
00223     {
00224         reducer.finish(reduce, reducedResult);
00225     }
00226 
00227     inline bool shouldThrottleThread()
00228     {
00229         return IterateKernelType::shouldThrottleThread() || reducer.shouldThrottle();
00230     }
00231 
00232     inline bool shouldStartThread()
00233     {
00234         return IterateKernelType::shouldStartThread() && reducer.shouldStartThread();
00235     }
00236 
00237     typedef ReducedResultType ReturnType;
00238     typedef ReducedResultType ResultType;
00239     ReducedResultType *result()
00240     {
00241         return &reducedResult;
00242     }
00243 };
00244 
00245 // Implementation of filter that reports individual results via QFutureInterface
00246 template <typename Iterator, typename KeepFunctor>
00247 class FilteredEachKernel : public IterateKernel<Iterator, typename qValueType<Iterator>::value_type>
00248 {
00249     typedef typename qValueType<Iterator>::value_type T;
00250     typedef IterateKernel<Iterator, T> IterateKernelType;
00251 
00252     KeepFunctor keep;
00253 
00254 public:
00255     typedef T ReturnType;
00256     typedef T ResultType;
00257 
00258     FilteredEachKernel(Iterator begin, Iterator end, KeepFunctor _keep)
00259         : IterateKernelType(begin, end), keep(_keep)
00260     { }
00261 
00262     void start()
00263     {
00264         if (this->futureInterface)
00265             this->futureInterface->setFilterMode(true);
00266         IterateKernelType::start();
00267     }
00268 
00269     bool runIteration(Iterator it, int index, T *)
00270     {
00271         if (keep(*it))
00272             this->reportResult(&(*it), index);
00273         else
00274             this->reportResult(0, index);
00275         return false;
00276     }
00277 
00278     bool runIterations(Iterator sequenceBeginIterator, int begin, int end, T *)
00279     {
00280         const int count = end - begin;
00281         IntermediateResults<typename qValueType<Iterator>::value_type> results;
00282         results.begin = begin;
00283         results.end = end;
00284         results.vector.reserve(count);
00285 
00286         Iterator it = sequenceBeginIterator;
00287         advance(it, begin);
00288         for (int i = begin; i < end; ++i) {
00289             if (keep(*it))
00290                 results.vector.append(*it);
00291             advance(it, 1);
00292         }
00293 
00294         this->reportResults(results.vector, begin, count);
00295         return false;
00296     }
00297 };
00298 
00299 template <typename Iterator, typename KeepFunctor>
00300 inline
00301 ThreadEngineStarter<typename qValueType<Iterator>::value_type>
00302 startFiltered(Iterator begin, Iterator end, KeepFunctor functor)
00303 {
00304     return startThreadEngine(new FilteredEachKernel<Iterator, KeepFunctor>(begin, end, functor));
00305 }
00306 
00307 template <typename Sequence, typename KeepFunctor>
00308 inline ThreadEngineStarter<typename Sequence::value_type>
00309 startFiltered(const Sequence &sequence, KeepFunctor functor)
00310 {
00311     typedef SequenceHolder1<Sequence,
00312                             FilteredEachKernel<typename Sequence::const_iterator, KeepFunctor>,
00313                             KeepFunctor>
00314         SequenceHolderType;
00315         return startThreadEngine(new SequenceHolderType(sequence, functor));
00316 }
00317 
00318 template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor>
00319 inline ThreadEngineStarter<ResultType> startFilteredReduced(const Sequence & sequence,
00320                                                            MapFunctor mapFunctor, ReduceFunctor reduceFunctor,
00321                                                            ReduceOptions options)
00322 {
00323     typedef typename Sequence::const_iterator Iterator;
00324     typedef ReduceKernel<ReduceFunctor, ResultType, typename qValueType<Iterator>::value_type > Reducer;
00325     typedef FilteredReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer> FilteredReduceType;
00326     typedef SequenceHolder2<Sequence, FilteredReduceType, MapFunctor, ReduceFunctor> SequenceHolderType;
00327     return startThreadEngine(new SequenceHolderType(sequence, mapFunctor, reduceFunctor, options));
00328 }
00329 
00330 
00331 template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
00332 inline ThreadEngineStarter<ResultType> startFilteredReduced(Iterator begin, Iterator end,
00333                                                            MapFunctor mapFunctor, ReduceFunctor reduceFunctor,
00334                                                            ReduceOptions options)
00335 {
00336     typedef ReduceKernel<ReduceFunctor, ResultType, typename qValueType<Iterator>::value_type> Reducer;
00337     typedef FilteredReducedKernel<ResultType, Iterator, MapFunctor, ReduceFunctor, Reducer> FilteredReduceType;
00338     return startThreadEngine(new FilteredReduceType(begin, end, mapFunctor, reduceFunctor, options));
00339 }
00340 
00341 
00342 } // namespace QtConcurrent
00343 
00344 #endif // qdoc
00345 
00346 QT_END_NAMESPACE
00347 QT_END_HEADER
00348 
00349 #endif // QT_NO_CONCURRENT
00350 
00351 #endif