Warning, file /include/QtCore/qthread.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005 #ifndef QTHREAD_H
0006 #define QTHREAD_H
0007
0008 #include <QtCore/qobject.h>
0009 #include <QtCore/qdeadlinetimer.h>
0010
0011
0012 #include <future> // for std::async
0013 #include <functional> // for std::invoke; no guard needed as it's a C++98 header
0014
0015 #if defined(Q_CC_MSVC) && defined(Q_PROCESSOR_X86)
0016 #include <intrin.h>
0017 #endif
0018
0019 QT_BEGIN_NAMESPACE
0020
0021
0022 class QThreadData;
0023 class QThreadPrivate;
0024 class QAbstractEventDispatcher;
0025 class QEventLoopLocker;
0026
0027 class Q_CORE_EXPORT QThread : public QObject
0028 {
0029 Q_OBJECT
0030 public:
0031 static Qt::HANDLE currentThreadId() noexcept Q_DECL_PURE_FUNCTION;
0032 static QThread *currentThread();
0033 static bool isMainThread() noexcept;
0034 static int idealThreadCount() noexcept;
0035 static void yieldCurrentThread();
0036
0037 explicit QThread(QObject *parent = nullptr);
0038 ~QThread();
0039
0040 enum Priority {
0041 IdlePriority,
0042
0043 LowestPriority,
0044 LowPriority,
0045 NormalPriority,
0046 HighPriority,
0047 HighestPriority,
0048
0049 TimeCriticalPriority,
0050
0051 InheritPriority
0052 };
0053
0054 enum class QualityOfService {
0055 Auto,
0056 High,
0057 Eco,
0058 };
0059 Q_ENUM(QualityOfService)
0060
0061 void setPriority(Priority priority);
0062 Priority priority() const;
0063
0064 bool isFinished() const;
0065 bool isRunning() const;
0066
0067 void requestInterruption();
0068 bool isInterruptionRequested() const;
0069
0070 void setStackSize(uint stackSize);
0071 uint stackSize() const;
0072
0073 QAbstractEventDispatcher *eventDispatcher() const;
0074 void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher);
0075
0076 bool event(QEvent *event) override;
0077 int loopLevel() const;
0078
0079 bool isCurrentThread() const noexcept;
0080
0081 void setServiceLevel(QualityOfService serviceLevel);
0082 QualityOfService serviceLevel() const;
0083
0084 template <typename Function, typename... Args>
0085 [[nodiscard]] static QThread *create(Function &&f, Args &&... args);
0086
0087 public Q_SLOTS:
0088 void start(Priority = InheritPriority);
0089 void terminate();
0090 void exit(int retcode = 0);
0091 void quit();
0092
0093 public:
0094 bool wait(QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever));
0095 bool wait(unsigned long time)
0096 {
0097 if (time == (std::numeric_limits<unsigned long>::max)())
0098 return wait(QDeadlineTimer(QDeadlineTimer::Forever));
0099 return wait(QDeadlineTimer(time));
0100 }
0101
0102 static void sleep(unsigned long);
0103 static void msleep(unsigned long);
0104 static void usleep(unsigned long);
0105 static void sleep(std::chrono::nanoseconds nsec);
0106
0107 Q_SIGNALS:
0108 void started(QPrivateSignal);
0109 void finished(QPrivateSignal);
0110
0111 protected:
0112 virtual void run();
0113 int exec();
0114
0115 static void setTerminationEnabled(bool enabled = true);
0116
0117 protected:
0118 QThread(QThreadPrivate &dd, QObject *parent = nullptr);
0119
0120 private:
0121 Q_DECLARE_PRIVATE(QThread)
0122 friend class QEventLoopLocker;
0123
0124 [[nodiscard]] static QThread *createThreadImpl(std::future<void> &&future);
0125 static Qt::HANDLE currentThreadIdImpl() noexcept Q_DECL_PURE_FUNCTION;
0126
0127 friend class QCoreApplication;
0128 friend class QThreadData;
0129 };
0130
0131 template <typename Function, typename... Args>
0132 QThread *QThread::create(Function &&f, Args &&... args)
0133 {
0134 using DecayedFunction = typename std::decay<Function>::type;
0135 auto threadFunction =
0136 [f = static_cast<DecayedFunction>(std::forward<Function>(f))](auto &&... largs) mutable -> void
0137 {
0138 (void)std::invoke(std::move(f), std::forward<decltype(largs)>(largs)...);
0139 };
0140
0141 return createThreadImpl(std::async(std::launch::deferred,
0142 std::move(threadFunction),
0143 std::forward<Args>(args)...));
0144 }
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159 inline Qt::HANDLE QThread::currentThreadId() noexcept
0160 {
0161
0162 #define QT_HAS_FAST_CURRENT_THREAD_ID
0163 Qt::HANDLE tid;
0164 static_assert(sizeof(tid) == sizeof(void*));
0165
0166 #if defined(Q_PROCESSOR_X86_32) && ((defined(Q_OS_LINUX) && defined(__GLIBC__)) || defined(Q_OS_FREEBSD))
0167 __asm__("mov %%gs:%c1, %0" : "=r" (tid) : "i" (2 * sizeof(void*)) : );
0168 #elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_DARWIN)
0169
0170 __asm__("mov %%gs:0, %0" : "=r" (tid) : : );
0171 #elif defined(Q_PROCESSOR_X86_64) && ((defined(Q_OS_LINUX) && defined(__GLIBC__)) || defined(Q_OS_FREEBSD))
0172
0173 __asm__("mov %%fs:%c1, %0" : "=r" (tid) : "i" (2 * sizeof(void*)) : );
0174 #elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_WIN)
0175
0176
0177 quint8 *tib;
0178 # if defined(Q_CC_MINGW)
0179 __asm__("movq %%gs:0x30, %0" : "=r" (tib) : :);
0180 # else
0181 tib = reinterpret_cast<quint8 *>(__readgsqword(0x30));
0182 # endif
0183
0184 tid = *reinterpret_cast<Qt::HANDLE *>(tib + 0x48);
0185 #elif defined(Q_PROCESSOR_X86_32) && defined(Q_OS_WIN)
0186
0187 quint8 *tib;
0188 # if defined(Q_CC_MINGW)
0189 __asm__("movl %%fs:0x18, %0" : "=r" (tib) : :);
0190 # else
0191 tib = reinterpret_cast<quint8 *>(__readfsdword(0x18));
0192 # endif
0193
0194 tid = *reinterpret_cast<Qt::HANDLE *>(tib + 0x24);
0195 #else
0196 #undef QT_HAS_FAST_CURRENT_THREAD_ID
0197 tid = currentThreadIdImpl();
0198 #endif
0199 return tid;
0200 }
0201
0202 QT_END_NAMESPACE
0203
0204 #endif