qtconcurrentthreadengine.h
上传用户:detong
上传日期:2022-06-22
资源大小:20675k
文件大小:8k
源码类别:

系统编程

开发平台:

Unix_Linux

  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
  4. ** Contact: Qt Software Information (qt-info@nokia.com)
  5. **
  6. ** This file is part of the QtCore module of the Qt Toolkit.
  7. **
  8. ** Commercial Usage
  9. ** Licensees holding valid Qt Commercial licenses may use this file in
  10. ** accordance with the Qt Commercial License Agreement provided with the
  11. ** Software or, alternatively, in accordance with the terms contained in
  12. ** a written agreement between you and Nokia.
  13. **
  14. **
  15. ** GNU General Public License Usage
  16. ** Alternatively, this file may be used under the terms of the GNU
  17. ** General Public License versions 2.0 or 3.0 as published by the Free
  18. ** Software Foundation and appearing in the file LICENSE.GPL included in
  19. ** the packaging of this file.  Please review the following information
  20. ** to ensure GNU General Public Licensing requirements will be met:
  21. ** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
  22. ** http://www.gnu.org/copyleft/gpl.html.  In addition, as a special
  23. ** exception, Nokia gives you certain additional rights. These rights
  24. ** are described in the Nokia Qt GPL Exception version 1.3, included in
  25. ** the file GPL_EXCEPTION.txt in this package.
  26. **
  27. ** Qt for Windows(R) Licensees
  28. ** As a special exception, Nokia, as the sole copyright holder for Qt
  29. ** Designer, grants users of the Qt/Eclipse Integration plug-in the
  30. ** right for the Qt/Eclipse Integration to link to functionality
  31. ** provided by Qt Designer and its related libraries.
  32. **
  33. ** If you are unsure which license is appropriate for your use, please
  34. ** contact the sales department at qt-sales@nokia.com.
  35. **
  36. ****************************************************************************/
  37. #ifndef QTCONCURRENT_THREADENGINE_H
  38. #define QTCONCURRENT_THREADENGINE_H
  39. #include <QtCore/qglobal.h>
  40. #ifndef QT_NO_CONCURRENT
  41. #include <QtCore/qthreadpool.h>
  42. #include <QtCore/qfuture.h>
  43. #include <QtCore/qdebug.h>
  44. #include <QtCore/qtconcurrentexception.h>
  45. #include <QtCore/qwaitcondition.h>
  46. QT_BEGIN_HEADER
  47. QT_BEGIN_NAMESPACE
  48. QT_MODULE(Core)
  49. #ifndef qdoc
  50. namespace QtConcurrent {
  51. // A Semaphore that can wait until all resources are returned.
  52. class ThreadEngineSemaphore
  53. {
  54. public:
  55.     ThreadEngineSemaphore()
  56.     :count(0) { }
  57.     void acquire()
  58.     {
  59.         QMutexLocker lock(&mutex);
  60.         ++count;
  61.     }
  62.     int release()
  63.     {
  64.         QMutexLocker lock(&mutex);
  65.         if (--count == 0)
  66.             waitCondition.wakeAll();
  67.         return count;
  68.     }
  69.     // Wait until all resources are released.
  70.     void wait()
  71.     {
  72.         QMutexLocker lock(&mutex);
  73.         if (count != 0)
  74.             waitCondition.wait(&mutex);
  75.     }
  76.     int currentCount()
  77.     {
  78.         return count;
  79.     }
  80.     // releases a resource, unless this is the last resource.
  81.     // returns true if a resource was released.
  82.     bool releaseUnlessLast()
  83.     {
  84.         QMutexLocker lock(&mutex);
  85.         if (count == 1)
  86.             return false;
  87.         --count;
  88.         return true;
  89.     }
  90. private:
  91.     QMutex mutex;
  92.     int count;
  93.     QWaitCondition waitCondition;
  94. };
  95. enum ThreadFunctionResult { ThrottleThread, ThreadFinished };
  96. // The ThreadEngine controls the threads used in the computation.
  97. // Can be run in three modes: single threaded, multi-threaded blocking
  98. // and multi-threaded asynchronous.
  99. // The code for the single threaded mode is
  100. class Q_CORE_EXPORT ThreadEngineBase: public QRunnable
  101. {
  102. public:
  103.     // Public API:
  104.     ThreadEngineBase();
  105.     virtual ~ThreadEngineBase();
  106.     void startSingleThreaded();
  107.     void startBlocking();
  108.     void startThread();
  109.     bool isCanceled();
  110.     bool isProgressReportingEnabled();
  111.     void setProgressValue(int progress);
  112.     void setProgressRange(int minimum, int maximum);
  113. protected: // The user overrides these:
  114.     virtual void start() {}
  115.     virtual void finish() {}
  116.     virtual ThreadFunctionResult threadFunction() { return ThreadFinished; }
  117.     virtual bool shouldStartThread() { return true; }
  118.     virtual bool shouldThrottleThread() { return false; }
  119. private:
  120.     bool startThreadInternal();
  121.     void startThreads();
  122.     void threadExit();
  123.     bool threadThrottleExit();
  124.     void run();
  125.     virtual void asynchronousFinish() = 0;
  126. #ifndef QT_NO_EXCEPTIONS
  127.     void handleException(const QtConcurrent::Exception &exception);
  128. #endif
  129. protected:
  130.     QFutureInterfaceBase *futureInterface;
  131.     QThreadPool *threadPool;
  132.     ThreadEngineSemaphore semaphore;
  133.     QtConcurrent::internal::ExceptionStore exceptionStore;
  134. };
  135. template <typename T>
  136. class ThreadEngine : public virtual ThreadEngineBase
  137. {
  138. public:
  139.     typedef T ResultType;
  140.     virtual T *result() { return 0; }
  141.     QFutureInterface<T> *futureInterfaceTyped()
  142.     {
  143.         return static_cast<QFutureInterface<T> *>(futureInterface);
  144.     }
  145.     // Runs the user algorithm using a single thread.
  146.     T *startSingleThreaded()
  147.     {
  148.         ThreadEngineBase::startSingleThreaded();
  149.         return result();
  150.     }
  151.     // Runs the user algorithm using multiple threads.
  152.     // This function blocks until the algorithm is finished,
  153.     // and then returns the result.
  154.     T *startBlocking()
  155.     {
  156.         ThreadEngineBase::startBlocking();
  157.         return result();
  158.     }
  159.     // Runs the user algorithm using multiple threads.
  160.     // Does not block, returns a future.
  161.     QFuture<T> startAsynchronously()
  162.     {
  163.         futureInterface = new QFutureInterface<T>();
  164.         // reportStart() must be called before starting threads, otherwise the
  165.         // user algorithm might finish while reportStart() is running, which
  166.         // is very bad.
  167.         futureInterface->reportStarted();
  168.         QFuture<T> future = QFuture<T>(futureInterfaceTyped());
  169.         start();
  170.         semaphore.acquire();
  171.         threadPool->start(this);
  172.         return future;
  173.     }
  174.     void asynchronousFinish()
  175.     {
  176.         finish();
  177.         futureInterfaceTyped()->reportFinished(result());
  178.         delete futureInterfaceTyped();
  179.         delete this;
  180.     }
  181.     void reportResult(const T *_result, int index = -1)
  182.     {
  183.         if (futureInterface)
  184.             futureInterfaceTyped()->reportResult(_result, index);
  185.     }
  186.     void reportResults(const QVector<T> &_result, int index = -1, int count = -1)
  187.     {
  188.         if (futureInterface)
  189.             futureInterfaceTyped()->reportResults(_result, index, count);
  190.     }
  191. };
  192. // The ThreadEngineStarter class ecapsulates the return type
  193. // from the thread engine.
  194. // Depending on how the it is used, it will run
  195. // the engine in either blocking mode or asynchronous mode.
  196. template <typename T>
  197. class ThreadEngineStarterBase
  198. {
  199. public:
  200.     ThreadEngineStarterBase(ThreadEngine<T> *_threadEngine)
  201.     : threadEngine(_threadEngine) { }
  202.     inline ThreadEngineStarterBase(const ThreadEngineStarterBase &other)
  203.     : threadEngine(other.threadEngine) { }
  204.     QFuture<T> startAsynchronously()
  205.     {
  206.         return threadEngine->startAsynchronously();
  207.     }
  208.     operator QFuture<T>()
  209.     {
  210.         return startAsynchronously();
  211.     }
  212. protected:
  213.     ThreadEngine<T> *threadEngine;
  214. };
  215. // We need to factor out the code that dereferences the T pointer,
  216. // with a specialization where T is void. (code that dereferences a void *
  217. // won't compile)
  218. template <typename T>
  219. class ThreadEngineStarter : public ThreadEngineStarterBase<T>
  220. {
  221. public:
  222.     ThreadEngineStarter(ThreadEngine<T> *threadEngine)
  223.     :ThreadEngineStarterBase<T>(threadEngine) {}
  224.     T startBlocking()
  225.     {
  226.         T t = *this->threadEngine->startBlocking();
  227.         delete this->threadEngine;
  228.         return t;
  229.     }
  230. };
  231. // Full template specialization where T is void.
  232. template <>
  233. class ThreadEngineStarter<void> : public ThreadEngineStarterBase<void>
  234. {
  235. public:
  236.     ThreadEngineStarter<void>(ThreadEngine<void> *_threadEngine)
  237.     :ThreadEngineStarterBase<void>(_threadEngine) {}
  238.     void startBlocking()
  239.     {
  240.         this->threadEngine->startBlocking();
  241.         delete this->threadEngine;
  242.     }
  243. };
  244. template <typename ThreadEngine>
  245. inline ThreadEngineStarter<typename ThreadEngine::ResultType> startThreadEngine(ThreadEngine *threadEngine)
  246. {
  247.     return ThreadEngineStarter<typename ThreadEngine::ResultType>(threadEngine);
  248. }
  249. } // namespace QtConcurrent
  250. #endif //qdoc
  251. QT_END_NAMESPACE
  252. QT_END_HEADER
  253. #endif // QT_NO_CONCURRENT
  254. #endif