qfutureinterface.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 QFUTUREINTERFACE_H
00043 #define QFUTUREINTERFACE_H
00044 
00045 #include <QtCore/qglobal.h>
00046 #include <QtCore/qrunnable.h>
00047 
00048 #ifndef QT_NO_QFUTURE
00049 
00050 #include <QtCore/qmutex.h>
00051 #include <QtCore/qtconcurrentexception.h>
00052 #include <QtCore/qtconcurrentresultstore.h>
00053 
00054 QT_BEGIN_HEADER
00055 QT_BEGIN_NAMESPACE
00056 
00057 QT_MODULE(Core)
00058 
00059 template <typename T> class QFuture;
00060 class QFutureInterfaceBasePrivate;
00061 class QFutureWatcherBase;
00062 class QFutureWatcherBasePrivate;
00063 
00064 class Q_CORE_EXPORT QFutureInterfaceBase
00065 {
00066 public:
00067     enum State {
00068         NoState   = 0x00,
00069         Running   = 0x01,
00070         Started   = 0x02,
00071         Finished  = 0x04,
00072         Canceled  = 0x08,
00073         Paused    = 0x10,
00074         Throttled = 0x20
00075     };
00076 
00077     QFutureInterfaceBase(State initialState = NoState);
00078     QFutureInterfaceBase(const QFutureInterfaceBase &other);
00079     virtual ~QFutureInterfaceBase();
00080 
00081     // reporting functions available to the engine author:
00082     void reportStarted();
00083     void reportFinished();
00084     void reportCanceled();
00085 #ifndef QT_NO_EXCEPTIONS
00086     void reportException(const QtConcurrent::Exception &e);
00087 #endif
00088     void reportResultsReady(int beginIndex, int endIndex);
00089 
00090     void setRunnable(QRunnable *runnable);
00091     void setFilterMode(bool enable);
00092     void setProgressRange(int minimum, int maximum);
00093     int progressMinimum() const;
00094     int progressMaximum() const;
00095     bool isProgressUpdateNeeded() const;
00096     void setProgressValue(int progressValue);
00097     int progressValue() const;
00098     void setProgressValueAndText(int progressValue, const QString &progressText);
00099     QString progressText() const;
00100 
00101     void setExpectedResultCount(int resultCount);
00102     int expectedResultCount();
00103     int resultCount() const;
00104 
00105     bool queryState(State state) const;
00106     bool isRunning() const;
00107     bool isStarted() const;
00108     bool isCanceled() const;
00109     bool isFinished() const;
00110     bool isPaused() const;
00111     bool isThrottled() const;
00112     bool isResultReadyAt(int index) const;
00113 
00114     void cancel();
00115     void setPaused(bool paused);
00116     void togglePaused();
00117     void setThrottled(bool enable);
00118 
00119     void waitForFinished();
00120     bool waitForNextResult();
00121     void waitForResult(int resultIndex);
00122     void waitForResume();
00123 
00124     QMutex *mutex() const;
00125     QtConcurrent::internal::ExceptionStore &exceptionStore();
00126     QtConcurrent::ResultStoreBase &resultStoreBase();
00127     const QtConcurrent::ResultStoreBase &resultStoreBase() const;
00128 
00129     inline bool operator==(const QFutureInterfaceBase &other) const { return d == other.d; }
00130     inline bool operator!=(const QFutureInterfaceBase &other) const { return d != other.d; }
00131     QFutureInterfaceBase &operator=(const QFutureInterfaceBase &other);
00132 
00133 protected:
00134     bool referenceCountIsOne() const;
00135 public:
00136 
00137 #ifndef QFUTURE_TEST
00138 private:
00139 #endif
00140     QFutureInterfaceBasePrivate *d;
00141 
00142 private:
00143     friend class QFutureWatcherBase;
00144     friend class QFutureWatcherBasePrivate;
00145 };
00146 
00147 template <typename T>
00148 class QFutureInterface : public QFutureInterfaceBase
00149 {
00150 public:
00151     QFutureInterface(State initialState = NoState)
00152         : QFutureInterfaceBase(initialState)
00153     { }
00154     QFutureInterface(const QFutureInterface &other)
00155         : QFutureInterfaceBase(other)
00156     { }
00157     ~QFutureInterface()
00158     {
00159         if (referenceCountIsOne())
00160             resultStore().clear();
00161     }
00162 
00163     static QFutureInterface canceledResult()
00164     { return QFutureInterface(State(Started | Finished | Canceled)); }
00165 
00166     QFutureInterface &operator=(const QFutureInterface &other)
00167     {
00168         if (referenceCountIsOne())
00169             resultStore().clear();
00170         QFutureInterfaceBase::operator=(other);
00171         return *this;
00172     }
00173 
00174     inline QFuture<T> future(); // implemented in qfuture.h
00175 
00176     inline void reportResult(const T *result, int index = -1);
00177     inline void reportResult(const T &result, int index = -1);
00178     inline void reportResults(const QVector<T> &results, int beginIndex = -1, int count = -1);
00179     inline void reportFinished(const T *result = 0);
00180 
00181     inline const T &resultReference(int index) const;
00182     inline const T *resultPointer(int index) const;
00183     inline QList<T> results();
00184 private:
00185     QtConcurrent::ResultStore<T> &resultStore()
00186     { return static_cast<QtConcurrent::ResultStore<T> &>(resultStoreBase()); }
00187     const QtConcurrent::ResultStore<T> &resultStore() const
00188     { return static_cast<const QtConcurrent::ResultStore<T> &>(resultStoreBase()); }
00189 };
00190 
00191 template <typename T>
00192 inline void QFutureInterface<T>::reportResult(const T *result, int index)
00193 {
00194     QMutexLocker locker(mutex());
00195     if (this->queryState(Canceled) || this->queryState(Finished)) {
00196         return;
00197     }
00198 
00199     QtConcurrent::ResultStore<T> &store = resultStore();
00200 
00201 
00202     if (store.filterMode()) {
00203         const int resultCountBefore = store.count();
00204         store.addResult(index, result);
00205         this->reportResultsReady(resultCountBefore, resultCountBefore + store.count());
00206     } else {
00207         const int insertIndex = store.addResult(index, result);
00208         this->reportResultsReady(insertIndex, insertIndex + 1);
00209     }
00210 }
00211 
00212 template <typename T>
00213 inline void QFutureInterface<T>::reportResult(const T &result, int index)
00214 {
00215     reportResult(&result, index);
00216 }
00217 
00218 template <typename T>
00219 inline void QFutureInterface<T>::reportResults(const QVector<T> &_results, int beginIndex, int count)
00220 {
00221     QMutexLocker locker(mutex());
00222     if (this->queryState(Canceled) || this->queryState(Finished)) {
00223         return;
00224     }
00225 
00226     QtConcurrent::ResultStore<T> &store = resultStore();
00227 
00228     if (store.filterMode()) {
00229         const int resultCountBefore = store.count();
00230         store.addResults(beginIndex, &_results, count);
00231         this->reportResultsReady(resultCountBefore, store.count());
00232     } else {
00233         const int insertIndex = store.addResults(beginIndex, &_results, count);
00234         this->reportResultsReady(insertIndex, insertIndex + _results.count());    
00235     }
00236 }
00237 
00238 template <typename T>
00239 inline void QFutureInterface<T>::reportFinished(const T *result)
00240 {
00241     if (result)
00242         reportResult(result);
00243     QFutureInterfaceBase::reportFinished();
00244 }
00245 
00246 template <typename T>
00247 inline const T &QFutureInterface<T>::resultReference(int index) const
00248 {
00249     QMutexLocker lock(mutex());
00250     return resultStore().resultAt(index).value();
00251 }
00252 
00253 template <typename T>
00254 inline const T *QFutureInterface<T>::resultPointer(int index) const
00255 {
00256     QMutexLocker lock(mutex());
00257     return resultStore().resultAt(index).pointer();
00258 }
00259 
00260 template <typename T>
00261 inline QList<T> QFutureInterface<T>::results()
00262 {
00263     if (this->isCanceled()) {
00264         exceptionStore().throwPossibleException();
00265         return QList<T>();
00266     }
00267     QFutureInterfaceBase::waitForResult(-1);
00268 
00269     QList<T> res;
00270     QMutexLocker lock(mutex());
00271 
00272     QtConcurrent::ResultIterator<T> it = resultStore().begin();
00273     while (it != resultStore().end()) {
00274         res.append(it.value());
00275         ++it;
00276     }
00277 
00278     return res;
00279 }
00280 
00281 template <>
00282 class QFutureInterface<void> : public QFutureInterfaceBase
00283 {
00284 public:
00285     QFutureInterface<void>(State initialState = NoState)
00286         : QFutureInterfaceBase(initialState)
00287     { }
00288     QFutureInterface<void>(const QFutureInterface<void> &other)
00289         : QFutureInterfaceBase(other)
00290     { }
00291 
00292     static QFutureInterface<void> canceledResult()
00293     { return QFutureInterface(State(Started | Finished | Canceled)); }
00294 
00295     QFutureInterface<void> &operator=(const QFutureInterface<void> &other)
00296     {
00297         QFutureInterfaceBase::operator=(other);
00298         return *this;
00299     }
00300 
00301     inline QFuture<void> future(); // implemented in qfuture.h
00302 
00303     void reportResult(const void *, int) { }
00304     void reportResults(const QVector<void> &, int) { }
00305     void reportFinished(void * = 0) { QFutureInterfaceBase::reportFinished(); }
00306 };
00307 
00308 QT_END_NAMESPACE
00309 QT_END_HEADER
00310 
00311 #endif // QT_NO_CONCURRENT
00312 
00313 #endif // QFUTUREINTERFACE_H