Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qthread_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
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_P_H
6#define QTHREAD_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18//
19
20#include "qplatformdefs.h"
21#include "QtCore/qthread.h"
22#include "QtCore/qmutex.h"
23#include "QtCore/qstack.h"
24#if QT_CONFIG(thread)
25#include "QtCore/qwaitcondition.h"
26#endif
27#include "QtCore/qmap.h"
28#include "QtCore/qcoreapplication.h"
29#include "private/qobject_p.h"
30
31#include <algorithm>
32#include <atomic>
33
35
37class QEventLoop;
38
40{
41public:
45 inline QPostEvent()
47 { }
48 inline QPostEvent(QObject *r, QEvent *e, int p)
49 : receiver(r), event(e), priority(p)
50 { }
51};
53
54inline bool operator<(const QPostEvent &first, const QPostEvent &second)
55{
56 return first.priority > second.priority;
57}
58
59// This class holds the list of posted events.
60// The list has to be kept sorted by priority
61// It's used in a virtual in QCoreApplication, so ELFVERSION:ignore-next
62class QPostEventList : public QList<QPostEvent>
63{
64public:
65 // recursion == recursion count for sendPostedEvents()
67
68 // sendOffset == the current event to start sending
70 // insertionOffset == set by sendPostedEvents to tell postEvent() where to start insertions
72
74
76
77 void addEvent(const QPostEvent &ev);
78
79private:
80 //hides because they do not keep that list sorted. addEvent must be used
83};
84
85namespace QtPrivate {
86
87/* BindingStatusOrList is basically a QBiPointer (as found in declarative)
88 with some helper methods to manipulate the list. BindingStatusOrList starts
89 its life in a null state and supports the following transitions
90
91 0 state (initial)
92 / \
93 / \
94 v v
95 pending object list----------->binding status
96 Note that binding status is the final state, and we never transition away
97 from it
98*/
100{
101 Q_DISABLE_COPY_MOVE(BindingStatusOrList)
102public:
103 using List = std::vector<QObject *>;
104
105 constexpr BindingStatusOrList() noexcept : data(0) {}
106 explicit BindingStatusOrList(QBindingStatus *status) noexcept :
107 data(encodeBindingStatus(status)) {}
108 explicit BindingStatusOrList(List *list) noexcept : data(encodeList(list)) {}
109
110 // requires external synchronization:
112 void removeObject(QObject *object);
113 void setStatusAndClearList(QBindingStatus *status) noexcept;
114
115
116 static bool isBindingStatus(quintptr data) noexcept
117 {
118 return !isNull(data) && !isList(data);
119 }
120 static bool isList(quintptr data) noexcept { return data & 1; }
121 static bool isNull(quintptr data) noexcept { return data == 0; }
122
123 // thread-safe:
125 {
126 // synchronizes-with the store-release in setStatusAndClearList():
127 const auto d = data.load(std::memory_order_acquire);
128 if (isBindingStatus(d))
129 return reinterpret_cast<QBindingStatus *>(d);
130 else
131 return nullptr;
132 }
133
134 // requires external synchronization:
135 List *list() const noexcept
136 {
137 return decodeList(data.load(std::memory_order_relaxed));
138 }
139
140private:
141 static List *decodeList(quintptr ptr) noexcept
142 {
143 if (isList(ptr))
144 return reinterpret_cast<List *>(ptr & ~1);
145 else
146 return nullptr;
147 }
148
149 static quintptr encodeBindingStatus(QBindingStatus *status) noexcept
150 {
151 return quintptr(status);
152 }
153
154 static quintptr encodeList(List *list) noexcept
155 {
156 return quintptr(list) | 1;
157 }
158
159 std::atomic<quintptr> data;
160};
161
162} // namespace QtPrivate
163
164#if QT_CONFIG(thread)
165
166class Q_CORE_EXPORT QDaemonThread : public QThread
167{
168public:
169 QDaemonThread(QObject *parent = nullptr);
170 ~QDaemonThread();
171};
172
173class QThreadPrivate : public QObjectPrivate
174{
175 Q_DECLARE_PUBLIC(QThread)
176
177public:
178 QThreadPrivate(QThreadData *d = nullptr);
180
182
183 mutable QMutex mutex;
184 QAtomicInt quitLockRef;
185
186 bool running;
187 bool finished;
188 bool isInFinish; //when in QThreadPrivate::finish
189 std::atomic<bool> interruptionRequested;
190
191 bool exited;
192 int returnCode;
193
194 uint stackSize;
195 std::underlying_type_t<QThread::Priority> priority;
196
197#ifdef Q_OS_UNIX
198 QWaitCondition thread_done;
199
200 static void *start(void *arg);
201 static void finish(void *);
202
203#endif // Q_OS_UNIX
204
205#ifdef Q_OS_WIN
206 static unsigned int __stdcall start(void *) noexcept;
207 static void finish(void *, bool lockAnyway = true) noexcept;
208
209 Qt::HANDLE handle;
210 unsigned int id;
211 int waiters;
212 bool terminationEnabled, terminatePending;
213#endif // Q_OS_WIN
214#ifdef Q_OS_WASM
215 static int idealThreadCount;
216#endif
218
220
221 void ref()
222 {
223 quitLockRef.ref();
224 }
225
226 void deref()
227 {
228 if (!quitLockRef.deref() && running) {
230 }
231 }
232
234 {
235 return m_statusOrPendingObjects.bindingStatus();
236 }
237
238 /* Returns nullptr if the object has been added, or the binding status
239 if that one has been set in the meantime
240 */
243
244 // manipulating m_statusOrPendingObjects requires mutex to be locked
245 QtPrivate::BindingStatusOrList m_statusOrPendingObjects = {};
246#ifndef Q_OS_INTEGRITY
247private:
248 // Used in QThread(Private)::start to avoid racy access to QObject::objectName,
249 // unset afterwards. On INTEGRITY we set the thread name before starting it.
250 QString objectName;
251#endif
252};
253
254#else // QT_CONFIG(thread)
255
257{
258public:
259 QThreadPrivate(QThreadData *d = nullptr);
261
262 mutable QMutex mutex;
265 bool running = false;
266
270
271 static void setCurrentThread(QThread *) { }
273
274 void ref() {}
275 void deref() {}
276
277 Q_DECLARE_PUBLIC(QThread)
278};
279
280#endif // QT_CONFIG(thread)
281
283{
284public:
285 QThreadData(int initialRefCount = 1);
286 ~QThreadData();
287
288 static Q_AUTOTEST_EXPORT QThreadData *current(bool createIfNecessary = true);
289 static void clearCurrentThreadData();
291 { Q_ASSERT_X(thread != nullptr, "QThread", "internal error"); return thread->d_func()->data; }
292
293
294 void ref();
295 void deref();
296 inline bool hasEventDispatcher() const
297 { return eventDispatcher.loadRelaxed() != nullptr; }
300 {
302 if (Q_LIKELY(ed))
303 return ed;
304 return createEventDispatcher();
305 }
306
308 {
310 return canWait;
311 }
312
313private:
314 QAtomicInt _ref;
315
316public:
319
326
331};
332
334{
335 QThreadData *threadData;
336public:
338 : threadData(threadData)
339 { ++threadData->scopeLevel; }
341 { --threadData->scopeLevel; }
342};
343
344// thread wrapper for the main() thread
346{
347 Q_DECLARE_PRIVATE(QThread)
348
349public:
350 QAdoptedThread(QThreadData *data = nullptr);
352 void init();
353
354private:
355#if QT_CONFIG(thread)
356 void run() override;
357#endif
358};
359
361
362#endif // QTHREAD_P_H
\inmodule QtCore
Definition qatomic.h:112
\macro Q_ATOMIC_INTnn_IS_SUPPORTED
Definition qatomic.h:123
bool ref() noexcept
bool deref() noexcept
Type loadRelaxed() const noexcept
static QCoreApplication * instance() noexcept
Returns a pointer to the application's QCoreApplication (or QGuiApplication/QApplication) instance.
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
\inmodule QtCore
Definition qeventloop.h:16
\inmodule QtCore
Definition qcoreevent.h:45
Definition qlist.h:74
iterator insert(qsizetype i, parameter_type t)
Definition qlist.h:471
void append(parameter_type t)
Definition qlist.h:441
\inmodule QtCore
Definition qmutex.h:317
\inmodule QtCore
Definition qmutex.h:285
QObject * q_ptr
Definition qobject.h:60
\inmodule QtCore
Definition qobject.h:90
void addEvent(const QPostEvent &ev)
Definition qthread.cpp:25
qsizetype startOffset
Definition qthread_p.h:69
qsizetype insertionOffset
Definition qthread_p.h:71
QObject * receiver
Definition qthread_p.h:42
QPostEvent(QObject *r, QEvent *e, int p)
Definition qthread_p.h:48
QEvent * event
Definition qthread_p.h:43
int priority
Definition qthread_p.h:44
QScopedScopeLevelCounter(QThreadData *threadData)
Definition qthread_p.h:337
\inmodule QtCore
Definition qstack.h:13
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static Q_AUTOTEST_EXPORT QThreadData * current(bool createIfNecessary=true)
Definition qthread.cpp:1005
QStack< QEventLoop * > eventLoops
Definition qthread_p.h:320
QAtomicPointer< QAbstractEventDispatcher > eventDispatcher
Definition qthread_p.h:324
bool requiresCoreApplication
Definition qthread_p.h:330
void deref()
Definition qthread.cpp:104
static void clearCurrentThreadData()
Definition qthread.cpp:1019
bool isAdopted
Definition qthread_p.h:329
QAtomicPointer< void > threadId
Definition qthread_p.h:323
static QThreadData * get2(QThread *thread)
Definition qthread_p.h:290
QAbstractEventDispatcher * ensureEventDispatcher()
Definition qthread_p.h:299
QPostEventList postEventList
Definition qthread_p.h:321
bool canWaitLocked()
Definition qthread_p.h:307
bool hasEventDispatcher() const
Definition qthread_p.h:296
void ref()
Definition qthread.cpp:96
QAtomicPointer< QThread > thread
Definition qthread_p.h:322
QList< void * > tls
Definition qthread_p.h:325
QAbstractEventDispatcher * createEventDispatcher()
Definition qthread.cpp:112
static void setCurrentThread(QThread *)
Definition qthread_p.h:271
static QAbstractEventDispatcher * createEventDispatcher(QThreadData *data)
void removeObjectWithPendingBindingStatusChange(QObject *)
Definition qthread_p.h:269
QThreadData * data
Definition qthread_p.h:263
QBindingStatus * m_bindingStatus
Definition qthread_p.h:264
QBindingStatus * bindingStatus()
Definition qthread_p.h:267
QBindingStatus * addObjectWithPendingBindingStatusChange(QObject *)
Definition qthread_p.h:268
virtual void run()
Definition qthread.cpp:913
BindingStatusOrList(List *list) noexcept
Definition qthread_p.h:108
List * list() const noexcept
Definition qthread_p.h:135
static bool isBindingStatus(quintptr data) noexcept
Definition qthread_p.h:116
static bool isNull(quintptr data) noexcept
Definition qthread_p.h:121
void removeObject(QObject *object)
void setStatusAndClearList(QBindingStatus *status) noexcept
constexpr BindingStatusOrList() noexcept
Definition qthread_p.h:105
QBindingStatus * addObjectUnlessAlreadyStatus(QObject *object)
BindingStatusOrList(QBindingStatus *status) noexcept
Definition qthread_p.h:106
QBindingStatus * bindingStatus() const noexcept
Definition qthread_p.h:124
std::vector< QObject * > List
Definition qthread_p.h:103
static bool isList(quintptr data) noexcept
Definition qthread_p.h:120
myinstance setPriority(MyClass::VeryHigh)
double e
Combined button and popup list for selecting options.
\macro QT_NAMESPACE
#define Q_LIKELY(x)
static ControlElement< T > * ptr(QWidget *widget)
GLuint64 GLenum void * handle
GLboolean r
[2]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint start
GLint first
struct _cl_event * event
GLhandleARB obj
[2]
GLfloat GLfloat p
[1]
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
SSL_CTX int(*) void arg)
#define Q_AUTOTEST_EXPORT
bool operator<(const QPostEvent &first, const QPostEvent &second)
Definition qthread_p.h:54
@ Q_RELOCATABLE_TYPE
Definition qtypeinfo.h:145
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS)
Definition qtypeinfo.h:163
size_t quintptr
Definition qtypes.h:72
ptrdiff_t qsizetype
Definition qtypes.h:70
unsigned int uint
Definition qtypes.h:29
QObject::connect nullptr
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent