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 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     On architectures and platforms we know, interpret the thread control
0135     block (TCB) as a unique identifier for a thread within a process. Otherwise,
0136     fall back to a slower but safe implementation.
0137 
0138     As per the documentation of currentThreadId, we return an opaque handle
0139     as a thread identifier, and application code is not supposed to use that
0140     value for anything. In Qt we use the handle to check if threads are identical,
0141     for which the TCB is sufficient.
0142 
0143     So we use the fastest possible way, rather than spend time on returning
0144     some pseudo-interoperable value.
0145 */
0146 inline Qt::HANDLE QThread::currentThreadId() noexcept
0147 {
0148     // define is undefed if we have to fall back to currentThreadIdImpl
0149 #define QT_HAS_FAST_CURRENT_THREAD_ID
0150     Qt::HANDLE tid; // typedef to void*
0151     static_assert(sizeof(tid) == sizeof(void*));
0152     // See https://akkadia.org/drepper/tls.pdf for x86 ABI
0153 #if defined(Q_PROCESSOR_X86_32) && ((defined(Q_OS_LINUX) && defined(__GLIBC__)) || defined(Q_OS_FREEBSD)) // x86 32-bit always uses GS
0154     __asm__("mov %%gs:%c1, %0" : "=r" (tid) : "i" (2 * sizeof(void*)) : );
0155 #elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_DARWIN)
0156     // 64bit macOS uses GS, see https://github.com/apple/darwin-xnu/blob/master/libsyscall/os/tsd.h
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     // x86_64 Linux, BSD uses FS
0160     __asm__("mov %%fs:%c1, %0" : "=r" (tid) : "i" (2 * sizeof(void*)) : );
0161 #elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_WIN)
0162     // See https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
0163     // First get the pointer to the TIB
0164     quint8 *tib;
0165 # if defined(Q_CC_MINGW) // internal compiler error when using the intrinsics
0166     __asm__("movq %%gs:0x30, %0" : "=r" (tib) : :);
0167 # else
0168     tib = reinterpret_cast<quint8 *>(__readgsqword(0x30));
0169 # endif
0170     // Then read the thread ID
0171     tid = *reinterpret_cast<Qt::HANDLE *>(tib + 0x48);
0172 #elif defined(Q_PROCESSOR_X86_32) && defined(Q_OS_WIN)
0173     // First get the pointer to the TIB
0174     quint8 *tib;
0175 # if defined(Q_CC_MINGW) // internal compiler error when using the intrinsics
0176     __asm__("movl %%fs:0x18, %0" : "=r" (tib) : :);
0177 # else
0178     tib = reinterpret_cast<quint8 *>(__readfsdword(0x18));
0179 # endif
0180     // Then read the thread ID
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 // QTHREAD_H