qtconcurrentresultstore.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_RESULTSTORE_H
00043 #define QTCONCURRENT_RESULTSTORE_H
00044 
00045 #include <QtCore/qglobal.h>
00046 
00047 #ifndef QT_NO_QFUTURE
00048 
00049 #include <QtCore/qmap.h>
00050 #include <QtCore/qdebug.h>
00051 
00052 QT_BEGIN_HEADER
00053 QT_BEGIN_NAMESPACE
00054 
00055 QT_MODULE(Core)
00056 
00057 /*
00058     ResultStore stores indexed results. Results can be added and retrieved
00059     either individually batched in a QVector. Retriveing results and checking
00060     which indexes are in the store can be done either by iterating or by random
00061     accees. In addition results kan be removed from the front of the store,
00062     either individually or in batches.
00063 */
00064 
00065 #ifndef qdoc
00066 
00067 namespace QtConcurrent {
00068 
00069 class ResultItem
00070 {
00071 public:
00072     ResultItem(const void *_result, int _count) : m_count(_count), result(_result) { } // contruct with vector of results
00073     ResultItem(const void *_result) : m_count(0), result(_result) { } // construct with result
00074     ResultItem() : m_count(0), result(0) { }
00075     bool isValid() const { return result != 0; }
00076     bool isVector() const { return m_count != 0; }
00077     int count() const { return (m_count == 0) ?  1 : m_count; }
00078     int m_count;          // result is either a pointer to a result or to a vector of results,
00079     const void *result; // if count is 0 it's a result, otherwise it's a vector.
00080 };
00081 
00082 class Q_CORE_EXPORT ResultIteratorBase
00083 {
00084 public:
00085     ResultIteratorBase();
00086     ResultIteratorBase(QMap<int, ResultItem>::const_iterator _mapIterator, int _vectorIndex = 0);
00087     int vectorIndex() const;
00088     int resultIndex() const;
00089 
00090     ResultIteratorBase operator++();
00091     int batchSize() const;
00092     void batchedAdvance();
00093     bool operator==(const ResultIteratorBase &other) const;
00094     bool operator!=(const ResultIteratorBase &other) const;
00095     bool isVector() const;
00096     bool canIncrementVectorIndex() const;
00097 protected:
00098     QMap<int, ResultItem>::const_iterator mapIterator;
00099     int m_vectorIndex;
00100 };
00101 
00102 template <typename T>
00103 class  ResultIterator : public ResultIteratorBase
00104 {
00105 public:
00106     ResultIterator(const ResultIteratorBase &base)
00107     : ResultIteratorBase(base) { }
00108 
00109     const T &value() const
00110     {
00111         return *pointer();
00112     }
00113 
00114     const T *pointer() const
00115     {
00116         if (mapIterator.value().isVector())
00117             return &(reinterpret_cast<const QVector<T> *>(mapIterator.value().result)->at(m_vectorIndex));
00118         else
00119             return reinterpret_cast<const T *>(mapIterator.value().result);
00120     }
00121 };
00122 
00123 class Q_CORE_EXPORT ResultStoreBase
00124 {
00125 public:
00126     ResultStoreBase();
00127     void setFilterMode(bool enable);
00128     bool filterMode() const;
00129     int addResult(int index, const void *result);
00130     int addResults(int index, const void *results, int vectorSize, int logicalCount);
00131     ResultIteratorBase begin() const;
00132     ResultIteratorBase end() const;
00133     bool hasNextResult() const;
00134     ResultIteratorBase resultAt(int index) const;
00135     bool contains(int index) const;
00136     int count() const;
00137     virtual ~ResultStoreBase() { };
00138 
00139 protected:
00140     int insertResultItem(int index, ResultItem &resultItem);
00141     void insertResultItemIfValid(int index, ResultItem &resultItem);
00142     void syncPendingResults();
00143     void syncResultCount();
00144     int updateInsertIndex(int index, int _count);
00145 
00146     QMap<int, ResultItem> m_results;
00147     int insertIndex;     // The index where the next results(s) will be inserted.
00148     int resultCount;     // The number of consecutive results stored, starting at index 0.
00149 
00150     bool m_filterMode;
00151     QMap<int, ResultItem> pendingResults;
00152     int filteredResults;
00153     
00154 };
00155 
00156 template <typename T>
00157 class ResultStore : public ResultStoreBase
00158 {
00159 public:
00160     ResultStore() { }
00161 
00162     ResultStore(const ResultStoreBase &base)
00163     : ResultStoreBase(base) { }
00164 
00165     int addResult(int index, const T  *result)
00166     {
00167         if (result == 0)
00168             return ResultStoreBase::addResult(index, result);
00169         else
00170             return ResultStoreBase::addResult(index, new T(*result));
00171     }
00172 
00173     int addResults(int index, const QVector<T> *results)
00174     {
00175         return ResultStoreBase::addResults(index, new QVector<T>(*results), results->count(), results->count());
00176     }
00177 
00178     int addResults(int index, const QVector<T> *results, int totalCount)
00179     {
00180         return ResultStoreBase::addResults(index, new QVector<T>(*results), results->count(), totalCount);
00181     }
00182 
00183     int addCanceledResult(int index)
00184     {
00185         return addResult(index, 0);
00186     }
00187 
00188     int addCanceledResults(int index, int _count)
00189     {
00190         QVector<T> empty;
00191         return addResults(index, &empty, _count);
00192     }
00193 
00194     ResultIterator<T> begin() const
00195     {
00196         return static_cast<ResultIterator<T> >(ResultStoreBase::begin());
00197     }
00198 
00199     ResultIterator<T> end() const
00200     {
00201         return static_cast<ResultIterator<T> >(ResultStoreBase::end());
00202     }
00203 
00204     ResultIterator<T> resultAt(int index) const
00205     {
00206         return static_cast<ResultIterator<T> >(ResultStoreBase::resultAt(index));
00207     }
00208 
00209     void clear()
00210     {
00211         QMap<int, ResultItem>::const_iterator mapIterator = m_results.constBegin();
00212         while (mapIterator != m_results.constEnd()) {
00213             if (mapIterator.value().isVector())
00214                 delete reinterpret_cast<const QVector<T> *>(mapIterator.value().result);
00215             else
00216                 delete reinterpret_cast<const T *>(mapIterator.value().result);
00217             ++mapIterator;
00218         }
00219         resultCount = 0;
00220         m_results.clear();
00221     }
00222 
00223     ~ResultStore()
00224     {
00225         clear();
00226     }
00227 
00228 };
00229 
00230 } // namespace QtConcurrent
00231 
00232 #endif //qdoc
00233 
00234 QT_END_NAMESPACE
00235 QT_END_HEADER
00236 
00237 #endif // QT_NO_CONCURRENT
00238 
00239 #endif