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 int idealThreadCount() noexcept;
0034 static void yieldCurrentThread();
0035
0036 explicit QThread(QObject *parent = nullptr);
0037 ~QThread();
0038
0039 enum Priority {
0040 IdlePriority,
0041
0042 LowestPriority,
0043 LowPriority,
0044 NormalPriority,
0045 HighPriority,
0046 HighestPriority,
0047
0048 TimeCriticalPriority,
0049
0050 InheritPriority
0051 };
0052
0053 void setPriority(Priority priority);
0054 Priority priority() const;
0055
0056 bool isFinished() const;
0057 bool isRunning() const;
0058
0059 void requestInterruption();
0060 bool isInterruptionRequested() const;
0061
0062 void setStackSize(uint stackSize);
0063 uint stackSize() const;
0064
0065 QAbstractEventDispatcher *eventDispatcher() const;
0066 void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher);
0067
0068 bool event(QEvent *event) override;
0069 int loopLevel() const;
0070
0071 template <typename Function, typename... Args>
0072 [[nodiscard]] static QThread *create(Function &&f, Args &&... args);
0073
0074 public Q_SLOTS:
0075 void start(Priority = InheritPriority);
0076 void terminate();
0077 void exit(int retcode = 0);
0078 void quit();
0079
0080 public:
0081 bool wait(QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever));
0082 bool wait(unsigned long time)
0083 {
0084 if (time == (std::numeric_limits<unsigned long>::max)())
0085 return wait(QDeadlineTimer(QDeadlineTimer::Forever));
0086 return wait(QDeadlineTimer(time));
0087 }
0088
0089 static void sleep(unsigned long);
0090 static void msleep(unsigned long);
0091 static void usleep(unsigned long);
0092 static void sleep(std::chrono::nanoseconds nsec);
0093
0094 Q_SIGNALS:
0095 void started(QPrivateSignal);
0096 void finished(QPrivateSignal);
0097
0098 protected:
0099 virtual void run();
0100 int exec();
0101
0102 static void setTerminationEnabled(bool enabled = true);
0103
0104 protected:
0105 QThread(QThreadPrivate &dd, QObject *parent = nullptr);
0106
0107 private:
0108 Q_DECLARE_PRIVATE(QThread)
0109 friend class QEventLoopLocker;
0110
0111 [[nodiscard]] static QThread *createThreadImpl(std::future<void> &&future);
0112 static Qt::HANDLE currentThreadIdImpl() noexcept Q_DECL_PURE_FUNCTION;
0113
0114 friend class QCoreApplication;
0115 friend class QThreadData;
0116 };
0117
0118 template <typename Function, typename... Args>
0119 QThread *QThread::create(Function &&f, Args &&... args)
0120 {
0121 using DecayedFunction = typename std::decay<Function>::type;
0122 auto threadFunction =
0123 [f = static_cast<DecayedFunction>(std::forward<Function>(f))](auto &&... largs) mutable -> void
0124 {
0125 (void)std::invoke(std::move(f), std::forward<decltype(largs)>(largs)...);
0126 };
0127
0128 return createThreadImpl(std::async(std::launch::deferred,
0129 std::move(threadFunction),
0130 std::forward<Args>(args)...));
0131 }
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146 inline Qt::HANDLE QThread::currentThreadId() noexcept
0147 {
0148
0149 #define QT_HAS_FAST_CURRENT_THREAD_ID
0150 Qt::HANDLE tid;
0151 static_assert(sizeof(tid) == sizeof(void*));
0152
0153 #if defined(Q_PROCESSOR_X86_32) && ((defined(Q_OS_LINUX) && defined(__GLIBC__)) || defined(Q_OS_FREEBSD))
0154 __asm__("mov %%gs:%c1, %0" : "=r" (tid) : "i" (2 * sizeof(void*)) : );
0155 #elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_DARWIN)
0156
0157 __asm__("mov %%gs:0, %0" : "=r" (tid) : : );
0158 #elif defined(Q_PROCESSOR_X86_64) && ((defined(Q_OS_LINUX) && defined(__GLIBC__)) || defined(Q_OS_FREEBSD))
0159
0160 __asm__("mov %%fs:%c1, %0" : "=r" (tid) : "i" (2 * sizeof(void*)) : );
0161 #elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_WIN)
0162
0163
0164 quint8 *tib;
0165 # if defined(Q_CC_MINGW)
0166 __asm__("movq %%gs:0x30, %0" : "=r" (tib) : :);
0167 # else
0168 tib = reinterpret_cast<quint8 *>(__readgsqword(0x30));
0169 # endif
0170
0171 tid = *reinterpret_cast<Qt::HANDLE *>(tib + 0x48);
0172 #elif defined(Q_PROCESSOR_X86_32) && defined(Q_OS_WIN)
0173
0174 quint8 *tib;
0175 # if defined(Q_CC_MINGW)
0176 __asm__("movl %%fs:0x18, %0" : "=r" (tib) : :);
0177 # else
0178 tib = reinterpret_cast<quint8 *>(__readfsdword(0x18));
0179 # endif
0180
0181 tid = *reinterpret_cast<Qt::HANDLE *>(tib + 0x24);
0182 #else
0183 #undef QT_HAS_FAST_CURRENT_THREAD_ID
0184 tid = currentThreadIdImpl();
0185 #endif
0186 return tid;
0187 }
0188
0189 QT_END_NAMESPACE
0190
0191 #endif