Back to home page

EIC code displayed by LXR

 
 

    


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 // Copyright (C) 2016 The Qt Company Ltd.
0002 // Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
0003 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0004 
0005 #ifndef QTHREAD_H
0006 #define QTHREAD_H
0007 
0008 #include <QtCore/qobject.h>
0009 #include <QtCore/qdeadlinetimer.h>
0010 
0011 // For QThread::create
0012 #include <future> // for std::async
0013 #include <functional> // for std::invoke; no guard needed as it's a C++98 header
0014 // internal compiler error with mingw 8.1
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     On architectures and platforms we know, interpret the thread control
0148     block (TCB) as a unique identifier for a thread within a process. Otherwise,
0149     fall back to a slower but safe implementation.
0150 
0151     As per the documentation of currentThreadId, we return an opaque handle
0152     as a thread identifier, and application code is not supposed to use that
0153     value for anything. In Qt we use the handle to check if threads are identical,
0154     for which the TCB is sufficient.
0155 
0156     So we use the fastest possible way, rather than spend time on returning
0157     some pseudo-interoperable value.
0158 */
0159 inline Qt::HANDLE QThread::currentThreadId() noexcept
0160 {
0161     // define is undefed if we have to fall back to currentThreadIdImpl
0162 #define QT_HAS_FAST_CURRENT_THREAD_ID
0163     Qt::HANDLE tid; // typedef to void*
0164     static_assert(sizeof(tid) == sizeof(void*));
0165     // See https://akkadia.org/drepper/tls.pdf for x86 ABI
0166 #if defined(Q_PROCESSOR_X86_32) && ((defined(Q_OS_LINUX) && defined(__GLIBC__)) || defined(Q_OS_FREEBSD)) // x86 32-bit always uses GS
0167     __asm__("mov %%gs:%c1, %0" : "=r" (tid) : "i" (2 * sizeof(void*)) : );
0168 #elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_DARWIN)
0169     // 64bit macOS uses GS, see https://github.com/apple/darwin-xnu/blob/master/libsyscall/os/tsd.h
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     // x86_64 Linux, BSD uses FS
0173     __asm__("mov %%fs:%c1, %0" : "=r" (tid) : "i" (2 * sizeof(void*)) : );
0174 #elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_WIN)
0175     // See https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
0176     // First get the pointer to the TIB
0177     quint8 *tib;
0178 # if defined(Q_CC_MINGW) // internal compiler error when using the intrinsics
0179     __asm__("movq %%gs:0x30, %0" : "=r" (tib) : :);
0180 # else
0181     tib = reinterpret_cast<quint8 *>(__readgsqword(0x30));
0182 # endif
0183     // Then read the thread ID
0184     tid = *reinterpret_cast<Qt::HANDLE *>(tib + 0x48);
0185 #elif defined(Q_PROCESSOR_X86_32) && defined(Q_OS_WIN)
0186     // First get the pointer to the TIB
0187     quint8 *tib;
0188 # if defined(Q_CC_MINGW) // internal compiler error when using the intrinsics
0189     __asm__("movl %%fs:0x18, %0" : "=r" (tib) : :);
0190 # else
0191     tib = reinterpret_cast<quint8 *>(__readfsdword(0x18));
0192 # endif
0193     // Then read the thread ID
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 // QTHREAD_H