Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qthread.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#ifndef QTHREAD_H
6#define QTHREAD_H
7
8#include <QtCore/qobject.h>
9#include <QtCore/qdeadlinetimer.h>
10
11// For QThread::create
12#if QT_CONFIG(cxx11_future)
13# include <future> // for std::async
14# include <functional> // for std::invoke; no guard needed as it's a C++98 header
15#endif
16// internal compiler error with mingw 8.1
17#if defined(Q_CC_MSVC) && defined(Q_PROCESSOR_X86)
18#include <intrin.h>
19#endif
20
22
23
24class QThreadData;
25class QThreadPrivate;
28
29class Q_CORE_EXPORT QThread : public QObject
30{
32public:
33 static Qt::HANDLE currentThreadId() noexcept Q_DECL_PURE_FUNCTION;
34 static QThread *currentThread();
35 static int idealThreadCount() noexcept;
36 static void yieldCurrentThread();
37
38 explicit QThread(QObject *parent = nullptr);
39 ~QThread();
40
41 enum Priority {
43
49
51
52 InheritPriority
53 };
54
55 void setPriority(Priority priority);
57
58 bool isFinished() const;
59 bool isRunning() const;
60
61 void requestInterruption();
62 bool isInterruptionRequested() const;
63
64 void setStackSize(uint stackSize);
65 uint stackSize() const;
66
67 QAbstractEventDispatcher *eventDispatcher() const;
68 void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher);
69
70 bool event(QEvent *event) override;
71 int loopLevel() const;
72
73#if QT_CONFIG(cxx11_future) || defined(Q_QDOC)
74 template <typename Function, typename... Args>
75 [[nodiscard]] static QThread *create(Function &&f, Args &&... args);
76#endif
77
78public Q_SLOTS:
79 void start(Priority = InheritPriority);
80 void terminate();
81 void exit(int retcode = 0);
82 void quit();
83
84public:
86 bool wait(unsigned long time)
87 {
88 if (time == (std::numeric_limits<unsigned long>::max)())
90 return wait(QDeadlineTimer(time));
91 }
92
93 static void sleep(unsigned long);
94 static void msleep(unsigned long);
95 static void usleep(unsigned long);
96 static void sleep(std::chrono::nanoseconds nsec);
97
99 void started(QPrivateSignal);
100 void finished(QPrivateSignal);
101
102protected:
103 virtual void run();
104 int exec();
105
106 static void setTerminationEnabled(bool enabled = true);
107
108protected:
109 QThread(QThreadPrivate &dd, QObject *parent = nullptr);
110
111private:
112 Q_DECLARE_PRIVATE(QThread)
113 friend class QEventLoopLocker;
114
115#if QT_CONFIG(cxx11_future)
116 [[nodiscard]] static QThread *createThreadImpl(std::future<void> &&future);
117#endif
118 static Qt::HANDLE currentThreadIdImpl() noexcept Q_DECL_PURE_FUNCTION;
119
120 friend class QCoreApplication;
121 friend class QThreadData;
122};
123
124#if QT_CONFIG(cxx11_future)
125template <typename Function, typename... Args>
126QThread *QThread::create(Function &&f, Args &&... args)
127{
128 using DecayedFunction = typename std::decay<Function>::type;
129 auto threadFunction =
130 [f = static_cast<DecayedFunction>(std::forward<Function>(f))](auto &&... largs) mutable -> void
131 {
132 (void)std::invoke(std::move(f), std::forward<decltype(largs)>(largs)...);
133 };
134
135 return createThreadImpl(std::async(std::launch::deferred,
136 std::move(threadFunction),
137 std::forward<Args>(args)...));
138}
139#endif // QT_CONFIG(cxx11_future)
140
141/*
142 On architectures and platforms we know, interpret the thread control
143 block (TCB) as a unique identifier for a thread within a process. Otherwise,
144 fall back to a slower but safe implementation.
145
146 As per the documentation of currentThreadId, we return an opaque handle
147 as a thread identifier, and application code is not supposed to use that
148 value for anything. In Qt we use the handle to check if threads are identical,
149 for which the TCB is sufficient.
150
151 So we use the fastest possible way, rather than spend time on returning
152 some pseudo-interoperable value.
153*/
155{
156 // define is undefed if we have to fall back to currentThreadIdImpl
157#define QT_HAS_FAST_CURRENT_THREAD_ID
158 Qt::HANDLE tid; // typedef to void*
159 static_assert(sizeof(tid) == sizeof(void*));
160 // See https://akkadia.org/drepper/tls.pdf for x86 ABI
161#if defined(Q_PROCESSOR_X86_32) && ((defined(Q_OS_LINUX) && defined(__GLIBC__)) || defined(Q_OS_FREEBSD)) // x86 32-bit always uses GS
162 __asm__("movl %%gs:%c1, %0" : "=r" (tid) : "i" (2 * sizeof(void*)) : );
163#elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_DARWIN)
164 // 64bit macOS uses GS, see https://github.com/apple/darwin-xnu/blob/master/libsyscall/os/tsd.h
165 __asm__("movq %%gs:0, %0" : "=r" (tid) : : );
166#elif defined(Q_PROCESSOR_X86_64) && ((defined(Q_OS_LINUX) && defined(__GLIBC__)) || defined(Q_OS_FREEBSD))
167 // x86_64 Linux, BSD uses FS
168 __asm__("movq %%fs:%c1, %0" : "=r" (tid) : "i" (2 * sizeof(void*)) : );
169#elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_WIN)
170 // See https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
171 // First get the pointer to the TIB
172 quint8 *tib;
173# if defined(Q_CC_MINGW) // internal compiler error when using the intrinsics
174 __asm__("movq %%gs:0x30, %0" : "=r" (tib) : :);
175# else
176 tib = reinterpret_cast<quint8 *>(__readgsqword(0x30));
177# endif
178 // Then read the thread ID
179 tid = *reinterpret_cast<Qt::HANDLE *>(tib + 0x48);
180#elif defined(Q_PROCESSOR_X86_32) && defined(Q_OS_WIN)
181 // First get the pointer to the TIB
182 quint8 *tib;
183# if defined(Q_CC_MINGW) // internal compiler error when using the intrinsics
184 __asm__("movl %%fs:0x18, %0" : "=r" (tib) : :);
185# else
186 tib = reinterpret_cast<quint8 *>(__readfsdword(0x18));
187# endif
188 // Then read the thread ID
189 tid = *reinterpret_cast<Qt::HANDLE *>(tib + 0x24);
190#else
191#undef QT_HAS_FAST_CURRENT_THREAD_ID
192 tid = currentThreadIdImpl();
193#endif
194 return tid;
195}
196
198
199#endif // QTHREAD_H
\inmodule QtCore
\inmodule QtCore
static constexpr ForeverConstant Forever
\inmodule QtCore
Definition qeventloop.h:59
\inmodule QtCore
Definition qcoreevent.h:45
\inmodule QtCore
Definition qobject.h:90
static void setTerminationEnabled(bool enabled=true)
bool wait(unsigned long time)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qthread.h:86
static Qt::HANDLE currentThreadId() noexcept Q_DECL_PURE_FUNCTION
Definition qthread.h:154
@ LowPriority
Definition qthread.h:45
@ LowestPriority
Definition qthread.h:44
@ TimeCriticalPriority
Definition qthread.h:50
@ HighestPriority
Definition qthread.h:48
@ IdlePriority
Definition qthread.h:42
@ NormalPriority
Definition qthread.h:46
@ HighPriority
Definition qthread.h:47
Priority priority() const
void finished(QPrivateSignal)
void setPriority(Priority priority)
int loopLevel() const
void started(QPrivateSignal)
Combined button and popup list for selecting options.
void * HANDLE
#define Q_DECL_PURE_FUNCTION
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLfloat GLfloat f
GLuint start
struct _cl_event * event
static bool isRunning()
Definition main.cpp:358
#define Q_OBJECT
#define Q_SLOTS
#define Q_SIGNALS
unsigned int uint
Definition qtypes.h:29
unsigned char quint8
Definition qtypes.h:41
QFuture< void > future
[5]
QDeadlineTimer deadline(30s)
dialog exec()
view create()
QJSValueList args
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent