QtBase  v6.3.1
qthread.h
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtCore module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #ifndef QTHREAD_H
42 #define QTHREAD_H
43 
44 #include <QtCore/qobject.h>
45 #include <QtCore/qdeadlinetimer.h>
46 
47 // For QThread::create
48 #if QT_CONFIG(cxx11_future)
49 # include <future> // for std::async
50 # include <functional> // for std::invoke; no guard needed as it's a C++98 header
51 #endif
52 // internal compiler error with mingw 8.1
53 #if defined(Q_CC_MSVC) && defined(Q_PROCESSOR_X86)
54 #include <intrin.h>
55 #endif
56 
58 
59 
60 class QThreadData;
61 class QThreadPrivate;
63 
64 class Q_CORE_EXPORT QThread : public QObject
65 {
66  Q_OBJECT
67 public:
68  static Qt::HANDLE currentThreadId() noexcept Q_DECL_PURE_FUNCTION;
69  static QThread *currentThread();
70  static int idealThreadCount() noexcept;
71  static void yieldCurrentThread();
72 
73  explicit QThread(QObject *parent = nullptr);
74  ~QThread();
75 
76  enum Priority {
78 
84 
86 
87  InheritPriority
88  };
89 
90  void setPriority(Priority priority);
91  Priority priority() const;
92 
93  bool isFinished() const;
94  bool isRunning() const;
95 
98 
99  void setStackSize(uint stackSize);
100  uint stackSize() const;
101 
102  QAbstractEventDispatcher *eventDispatcher() const;
103  void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher);
104 
105  bool event(QEvent *event) override;
106  int loopLevel() const;
107 
108 #if QT_CONFIG(cxx11_future) || defined(Q_CLANG_QDOC)
109  template <typename Function, typename... Args>
110  [[nodiscard]] static QThread *create(Function &&f, Args &&... args);
111 #endif
112 
113 public Q_SLOTS:
114  void start(Priority = InheritPriority);
115  void terminate();
116  void exit(int retcode = 0);
117  void quit();
118 
119 public:
121  bool wait(unsigned long time)
122  {
123  if (time == (std::numeric_limits<unsigned long>::max)())
125  return wait(QDeadlineTimer(time));
126  }
127 
128  static void sleep(unsigned long);
129  static void msleep(unsigned long);
130  static void usleep(unsigned long);
131 
132 Q_SIGNALS:
133  void started(QPrivateSignal);
134  void finished(QPrivateSignal);
135 
136 protected:
137  virtual void run();
138  int exec();
139 
140  static void setTerminationEnabled(bool enabled = true);
141 
142 protected:
143  QThread(QThreadPrivate &dd, QObject *parent = nullptr);
144 
145 private:
146  Q_DECLARE_PRIVATE(QThread)
147 
148 #if QT_CONFIG(cxx11_future)
149  [[nodiscard]] static QThread *createThreadImpl(std::future<void> &&future);
150 #endif
151  static Qt::HANDLE currentThreadIdImpl() noexcept Q_DECL_PURE_FUNCTION;
152 
153  friend class QCoreApplication;
154  friend class QThreadData;
155 };
156 
157 #if QT_CONFIG(cxx11_future)
158 template <typename Function, typename... Args>
160 {
161  using DecayedFunction = typename std::decay<Function>::type;
162  auto threadFunction =
163  [f = static_cast<DecayedFunction>(std::forward<Function>(f))](auto &&... largs) mutable -> void
164  {
165  (void)std::invoke(std::move(f), std::forward<decltype(largs)>(largs)...);
166  };
167 
168  return createThreadImpl(std::async(std::launch::deferred,
169  std::move(threadFunction),
170  std::forward<Args>(args)...));
171 }
172 #endif // QT_CONFIG(cxx11_future)
173 
174 /*
175  On architectures and platforms we know, interpret the thread control
176  block (TCB) as a unique identifier for a thread within a process. Otherwise,
177  fall back to a slower but safe implementation.
178 
179  As per the documentation of currentThreadId, we return an opaque handle
180  as a thread identifier, and application code is not supposed to use that
181  value for anything. In Qt we use the handle to check if threads are identical,
182  for which the TCB is sufficient.
183 
184  So we use the fastest possible way, rather than spend time on returning
185  some pseudo-interoperable value.
186 */
188 {
189  // define is undefed if we have to fall back to currentThreadIdImpl
190 #define QT_HAS_FAST_CURRENT_THREAD_ID
191  Qt::HANDLE tid; // typedef to void*
192  static_assert(sizeof(tid) == sizeof(void*));
193  // See https://akkadia.org/drepper/tls.pdf for x86 ABI
194 #if defined(Q_PROCESSOR_X86_32) && defined(Q_OS_LINUX) && defined(__GLIBC__) // x86 32-bit always uses GS
195  __asm__("movl %%gs:%c1, %0" : "=r" (tid) : "i" (2 * sizeof(void*)) : );
196 #elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_DARWIN64)
197  // 64bit macOS uses GS, see https://github.com/apple/darwin-xnu/blob/master/libsyscall/os/tsd.h
198  __asm__("movq %%gs:0, %0" : "=r" (tid) : : );
199 #elif defined(Q_PROCESSOR_X86_64) && (defined(Q_OS_LINUX) && defined(__GLIBC__)) || defined(Q_OS_FREEBSD)
200  // x86_64 Linux, BSD uses FS
201  __asm__("movq %%fs:%c1, %0" : "=r" (tid) : "i" (2 * sizeof(void*)) : );
202 #elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_WIN)
203  // See https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
204  // First get the pointer to the TIB
205  quint8 *tib;
206 # if defined(Q_CC_MINGW) // internal compiler error when using the intrinsics
207  __asm__("movq %%gs:0x30, %0" : "=r" (tib) : :);
208 # else
209  tib = reinterpret_cast<quint8 *>(__readgsqword(0x30));
210 # endif
211  // Then read the thread ID
212  tid = *reinterpret_cast<Qt::HANDLE *>(tib + 0x48);
213 #elif defined(Q_PROCESSOR_X86_32) && defined(Q_OS_WIN)
214  // First get the pointer to the TIB
215  quint8 *tib;
216 # if defined(Q_CC_MINGW) // internal compiler error when using the intrinsics
217  __asm__("movl %%fs:0x18, %0" : "=r" (tib) : :);
218 # else
219  tib = reinterpret_cast<quint8 *>(__readfsdword(0x18));
220 # endif
221  // Then read the thread ID
222  tid = *reinterpret_cast<Qt::HANDLE *>(tib + 0x24);
223 #else
224 #undef QT_HAS_FAST_CURRENT_THREAD_ID
225  tid = currentThreadIdImpl();
226 #endif
227  return tid;
228 }
229 
231 
232 #endif // QTHREAD_H
The QAbstractEventDispatcher class provides an interface to manage Qt's event queue.
The QCoreApplication class provides an event loop for Qt applications without UI.
The QDeadlineTimer class marks a deadline in the future.
The QEvent class is the base class of all event classes. Event objects contain event parameters.
Definition: qcoreevent.h:58
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
virtual bool event(QEvent *event)
Definition: qobject.cpp:1329
bool isInterruptionRequested() const
static void setTerminationEnabled(bool enabled=true)
bool wait(unsigned long time)
Definition: qthread.h:121
static Qt::HANDLE currentThreadId() noexcept Q_DECL_PURE_FUNCTION
Definition: qthread.h:187
Priority
Definition: qthread.h:76
@ LowPriority
Definition: qthread.h:80
@ LowestPriority
Definition: qthread.h:79
@ TimeCriticalPriority
Definition: qthread.h:85
@ HighestPriority
Definition: qthread.h:83
@ IdlePriority
Definition: qthread.h:77
@ NormalPriority
Definition: qthread.h:81
@ HighPriority
Definition: qthread.h:82
Priority priority() const
void finished(QPrivateSignal)
void setPriority(Priority priority)
void requestInterruption()
int loopLevel() const
void started(QPrivateSignal)
msgBox exec()
void * HANDLE
Definition: qnamespace.h:1561
void
Definition: png.h:1080
#define Q_DECL_PURE_FUNCTION
unsigned int uint
Definition: qglobal.h:334
unsigned char quint8
Definition: qglobal.h:284
GLenum type
Definition: qopengl.h:270
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLfloat GLfloat f
GLuint start
struct _cl_event * event
Definition: qopenglext.h:2998
#define Q_OBJECT
Definition: qtmetamacros.h:158
#define Q_SLOTS
Definition: qtmetamacros.h:80
#define Q_SIGNALS
Definition: qtmetamacros.h:81
int usleep(useconds_t)
QFuture< void > future
[5]
QDeadlineTimer deadline(30s)
QTime time
[5]
view create()
Definition: main.cpp:58
bool run(const QString &name, QString *errorMessage)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent