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