File indexing completed on 2025-10-30 08:50:49
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