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 // Qt-Security score:significant reason:default
0005 
0006 #ifndef QTHREAD_H
0007 #define QTHREAD_H
0008 
0009 #include <QtCore/qobject.h>
0010 #include <QtCore/qdeadlinetimer.h>
0011 
0012 // For QThread::create
0013 #include <future> // for std::async
0014 #include <functional> // for std::invoke; no guard needed as it's a C++98 header
0015 // internal compiler error with mingw 8.1
0016 #if defined(Q_CC_MSVC) && defined(Q_PROCESSOR_X86)
0017 #include <intrin.h>
0018 #endif
0019 
0020 QT_BEGIN_NAMESPACE
0021 
0022 
0023 class QThreadData;
0024 class QThreadPrivate;
0025 class QAbstractEventDispatcher;
0026 class QEventLoopLocker;
0027 
0028 class Q_CORE_EXPORT QThread : public QObject
0029 {
0030     Q_OBJECT
0031 public:
0032     static Qt::HANDLE currentThreadId() noexcept Q_DECL_PURE_FUNCTION;
0033     static QThread *currentThread();
0034     static bool isMainThread() noexcept;
0035     static int idealThreadCount() noexcept;
0036     static void yieldCurrentThread();
0037 
0038     explicit QThread(QObject *parent = nullptr);
0039     ~QThread();
0040 
0041     enum Priority {
0042         IdlePriority,
0043 
0044         LowestPriority,
0045         LowPriority,
0046         NormalPriority,
0047         HighPriority,
0048         HighestPriority,
0049 
0050         TimeCriticalPriority,
0051 
0052         InheritPriority
0053     };
0054 
0055     enum class QualityOfService {
0056         Auto,
0057         High,
0058         Eco,
0059     };
0060     Q_ENUM(QualityOfService)
0061 
0062     void setPriority(Priority priority);
0063     Priority priority() const;
0064 
0065     bool isFinished() const;
0066     bool isRunning() const;
0067 
0068     void requestInterruption();
0069     bool isInterruptionRequested() const;
0070 
0071     void setStackSize(uint stackSize);
0072     uint stackSize() const;
0073 
0074     QAbstractEventDispatcher *eventDispatcher() const;
0075     void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher);
0076 
0077     bool event(QEvent *event) override;
0078     int loopLevel() const;
0079 
0080     bool isCurrentThread() const noexcept;
0081 
0082     void setServiceLevel(QualityOfService serviceLevel);
0083     QualityOfService serviceLevel() const;
0084 
0085     template <typename Function, typename... Args>
0086     [[nodiscard]] static QThread *create(Function &&f, Args &&... args);
0087 
0088 public Q_SLOTS:
0089     void start(Priority = InheritPriority);
0090     void terminate();
0091     void exit(int retcode = 0);
0092     void quit();
0093 
0094 public:
0095     bool wait(QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever));
0096     bool wait(unsigned long time)
0097     {
0098         if (time == (std::numeric_limits<unsigned long>::max)())
0099             return wait(QDeadlineTimer(QDeadlineTimer::Forever));
0100         return wait(QDeadlineTimer(time));
0101     }
0102 
0103     static void sleep(unsigned long);
0104     static void msleep(unsigned long);
0105     static void usleep(unsigned long);
0106     static void sleep(std::chrono::nanoseconds nsec);
0107 
0108 Q_SIGNALS:
0109     void started(QPrivateSignal);
0110     void finished(QPrivateSignal);
0111 
0112 protected:
0113     virtual void run();
0114     int exec();
0115 
0116     static void setTerminationEnabled(bool enabled = true);
0117 
0118 protected:
0119     QThread(QThreadPrivate &dd, QObject *parent = nullptr);
0120 
0121 private:
0122     Q_DECLARE_PRIVATE(QThread)
0123     friend class QEventLoopLocker;
0124 
0125     [[nodiscard]] static QThread *createThreadImpl(std::future<void> &&future);
0126     static Qt::HANDLE currentThreadIdImpl() noexcept Q_DECL_PURE_FUNCTION;
0127 
0128     friend class QCoreApplication;
0129     friend class QThreadData;
0130 };
0131 
0132 template <typename Function, typename... Args>
0133 QThread *QThread::create(Function &&f, Args &&... args)
0134 {
0135     using DecayedFunction = typename std::decay<Function>::type;
0136     auto threadFunction =
0137         [f = static_cast<DecayedFunction>(std::forward<Function>(f))](auto &&... largs) mutable -> void
0138         {
0139             (void)std::invoke(std::move(f), std::forward<decltype(largs)>(largs)...);
0140         };
0141 
0142     return createThreadImpl(std::async(std::launch::deferred,
0143                                        std::move(threadFunction),
0144                                        std::forward<Args>(args)...));
0145 }
0146 
0147 /*
0148     On architectures and platforms we know, interpret the thread control
0149     block (TCB) as a unique identifier for a thread within a process. Otherwise,
0150     fall back to a slower but safe implementation.
0151 
0152     As per the documentation of currentThreadId, we return an opaque handle
0153     as a thread identifier, and application code is not supposed to use that
0154     value for anything. In Qt we use the handle to check if threads are identical,
0155     for which the TCB is sufficient.
0156 
0157     So we use the fastest possible way, rather than spend time on returning
0158     some pseudo-interoperable value.
0159 */
0160 inline Qt::HANDLE QThread::currentThreadId() noexcept
0161 {
0162     // define is undefed if we have to fall back to currentThreadIdImpl
0163 #define QT_HAS_FAST_CURRENT_THREAD_ID
0164     Qt::HANDLE tid; // typedef to void*
0165     static_assert(sizeof(tid) == sizeof(void*));
0166     // See https://akkadia.org/drepper/tls.pdf for x86 ABI
0167 #if defined(Q_PROCESSOR_X86_32) && ((defined(Q_OS_LINUX) && defined(__GLIBC__)) || defined(Q_OS_FREEBSD)) // x86 32-bit always uses GS
0168     __asm__("mov %%gs:%c1, %0" : "=r" (tid) : "i" (2 * sizeof(void*)) : );
0169 #elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_DARWIN)
0170     // 64bit macOS uses GS, see https://github.com/apple/darwin-xnu/blob/master/libsyscall/os/tsd.h
0171     __asm__("mov %%gs:0, %0" : "=r" (tid) : : );
0172 #elif defined(Q_PROCESSOR_X86_64) && ((defined(Q_OS_LINUX) && defined(__GLIBC__)) || defined(Q_OS_FREEBSD))
0173     // x86_64 Linux, BSD uses FS
0174     __asm__("mov %%fs:%c1, %0" : "=r" (tid) : "i" (2 * sizeof(void*)) : );
0175 #elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_WIN) && defined(Q_CC_MSVC)
0176     // See https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
0177     tid = reinterpret_cast<Qt::HANDLE>(__readgsqword(0x48));
0178 #elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_WIN) // !Q_CC_MSVC
0179     __asm__("mov %%gs:0x48, %0" : "=r" (tid));
0180 #elif defined(Q_PROCESSOR_X86_32) && defined(Q_OS_WIN) && defined(Q_CC_MSVC)
0181     tid = reinterpret_cast<Qt::HANDLE>(__readfsdword(0x24));
0182 #elif defined(Q_PROCESSOR_X86_32) && defined(Q_OS_WIN) // !Q_CC_MSVC
0183     __asm__("mov %%fs:0x24, %0" : "=r" (tid));
0184 #else
0185 #undef QT_HAS_FAST_CURRENT_THREAD_ID
0186     tid = currentThreadIdImpl();
0187 #endif
0188     return tid;
0189 }
0190 
0191 QT_END_NAMESPACE
0192 
0193 #endif // QTHREAD_H