File indexing completed on 2025-02-21 10:09:51
0001
0002
0003
0004 #ifndef QTCONCURRENT_THREADENGINE_H
0005 #define QTCONCURRENT_THREADENGINE_H
0006
0007 #include <QtConcurrent/qtconcurrent_global.h>
0008
0009 #if !defined(QT_NO_CONCURRENT) ||defined(Q_QDOC)
0010
0011 #include <QtCore/qthreadpool.h>
0012 #include <QtCore/qfuture.h>
0013 #include <QtCore/qdebug.h>
0014 #include <QtCore/qexception.h>
0015 #include <QtCore/qwaitcondition.h>
0016 #include <QtCore/qatomic.h>
0017 #include <QtCore/qsemaphore.h>
0018
0019 QT_BEGIN_NAMESPACE
0020
0021
0022 namespace QtConcurrent {
0023
0024
0025
0026
0027 class ThreadEngineBarrier
0028 {
0029 private:
0030
0031
0032
0033
0034 QAtomicInt count;
0035 QSemaphore semaphore;
0036 public:
0037 ThreadEngineBarrier();
0038 void acquire();
0039 int release();
0040 void wait();
0041 int currentCount();
0042 bool releaseUnlessLast();
0043 };
0044
0045 enum ThreadFunctionResult { ThrottleThread, ThreadFinished };
0046
0047
0048
0049
0050
0051 class Q_CONCURRENT_EXPORT ThreadEngineBase: public QRunnable
0052 {
0053 public:
0054
0055 ThreadEngineBase(QThreadPool *pool);
0056 virtual ~ThreadEngineBase();
0057 void startSingleThreaded();
0058 void startThread();
0059 bool isCanceled();
0060 void waitForResume();
0061 bool isProgressReportingEnabled();
0062 void setProgressValue(int progress);
0063 void setProgressRange(int minimum, int maximum);
0064 void acquireBarrierSemaphore();
0065 void reportIfSuspensionDone() const;
0066
0067 protected:
0068 virtual void start() {}
0069 virtual void finish() {}
0070 virtual ThreadFunctionResult threadFunction() { return ThreadFinished; }
0071 virtual bool shouldStartThread() { return !shouldThrottleThread(); }
0072 virtual bool shouldThrottleThread()
0073 {
0074 return futureInterface ? (futureInterface->isSuspending() || futureInterface->isSuspended())
0075 : false;
0076 }
0077
0078 private:
0079 bool startThreadInternal();
0080 void startThreads();
0081 void threadExit();
0082 bool threadThrottleExit();
0083 void run() override;
0084 virtual void asynchronousFinish() = 0;
0085 #ifndef QT_NO_EXCEPTIONS
0086 void handleException(const QException &exception);
0087 #endif
0088 protected:
0089 QFutureInterfaceBase *futureInterface;
0090 QThreadPool *threadPool;
0091 ThreadEngineBarrier barrier;
0092 QtPrivate::ExceptionStore exceptionStore;
0093 QBasicMutex mutex;
0094 };
0095
0096
0097 template <typename T>
0098 class ThreadEngine : public ThreadEngineBase
0099 {
0100 public:
0101 typedef T ResultType;
0102
0103 ThreadEngine(QThreadPool *pool) : ThreadEngineBase(pool) {}
0104
0105 virtual T *result() { return nullptr; }
0106
0107 QFutureInterface<T> *futureInterfaceTyped()
0108 {
0109 return static_cast<QFutureInterface<T> *>(futureInterface);
0110 }
0111
0112
0113 T *startSingleThreaded()
0114 {
0115 ThreadEngineBase::startSingleThreaded();
0116 return result();
0117 }
0118
0119
0120
0121 QFuture<T> startAsynchronously()
0122 {
0123 futureInterface = new QFutureInterface<T>();
0124
0125
0126
0127
0128 futureInterface->reportStarted();
0129 QFuture<T> future = QFuture<T>(futureInterfaceTyped());
0130 start();
0131
0132 acquireBarrierSemaphore();
0133 threadPool->start(this);
0134 return future;
0135 }
0136
0137 void asynchronousFinish() override
0138 {
0139 finish();
0140 futureInterfaceTyped()->reportFinished(result());
0141 delete futureInterfaceTyped();
0142 delete this;
0143 }
0144
0145
0146 void reportResult(const T *_result, int index = -1)
0147 {
0148 if (futureInterface)
0149 futureInterfaceTyped()->reportResult(_result, index);
0150 }
0151
0152 void reportResults(const QList<T> &_result, int index = -1, int count = -1)
0153 {
0154 if (futureInterface)
0155 futureInterfaceTyped()->reportResults(_result, index, count);
0156 }
0157 };
0158
0159
0160
0161
0162
0163 template <typename T>
0164 class ThreadEngineStarterBase
0165 {
0166 public:
0167 ThreadEngineStarterBase(ThreadEngine<T> *_threadEngine)
0168 : threadEngine(_threadEngine) { }
0169
0170 inline ThreadEngineStarterBase(const ThreadEngineStarterBase &other)
0171 : threadEngine(other.threadEngine) { }
0172
0173 QFuture<T> startAsynchronously()
0174 {
0175 return threadEngine->startAsynchronously();
0176 }
0177
0178 operator QFuture<T>()
0179 {
0180 return startAsynchronously();
0181 }
0182
0183 protected:
0184 ThreadEngine<T> *threadEngine;
0185 };
0186
0187
0188
0189
0190
0191 template <typename T>
0192 class ThreadEngineStarter : public ThreadEngineStarterBase<T>
0193 {
0194 typedef ThreadEngineStarterBase<T> Base;
0195 typedef ThreadEngine<T> TypedThreadEngine;
0196 public:
0197 ThreadEngineStarter(TypedThreadEngine *eng)
0198 : Base(eng) { }
0199 };
0200
0201
0202 template <>
0203 class ThreadEngineStarter<void> : public ThreadEngineStarterBase<void>
0204 {
0205 public:
0206 ThreadEngineStarter(ThreadEngine<void> *_threadEngine)
0207 : ThreadEngineStarterBase<void>(_threadEngine) {}
0208 };
0209
0210
0211 template <typename ThreadEngine>
0212 inline ThreadEngineStarter<typename ThreadEngine::ResultType> startThreadEngine(ThreadEngine *threadEngine)
0213 {
0214 return ThreadEngineStarter<typename ThreadEngine::ResultType>(threadEngine);
0215 }
0216
0217 }
0218
0219
0220 QT_END_NAMESPACE
0221
0222 #endif
0223
0224 #endif