Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
174{
175 Q_DECLARE_PUBLIC(QThread)
176
177public:
178 QThreadPrivate(QThreadData *d = nullptr);
180
182 Qt::HANDLE threadId() const;
183
184 mutable QMutex mutex;
185 QAtomicInt quitLockRef;
186
187 bool running;
188 bool finished;
189 bool isInFinish; //when in QThreadPrivate::finish
190 std::atomic<bool> interruptionRequested;
191
192 bool exited;
193 int returnCode;
194
195 uint stackSize;
196 std::underlying_type_t<QThread::Priority> priority;
197
198#ifdef Q_OS_UNIX
199 QWaitCondition thread_done;
200
201 static void *start(void *arg);
202 static void finish(void *);
203
204#endif // Q_OS_UNIX
205
206#ifdef Q_OS_WIN
207 static unsigned int __stdcall start(void *) noexcept;
208 static void finish(void *, bool lockAnyway = true) noexcept;
209
210 Qt::HANDLE handle;
211 unsigned int id;
212 int waiters;
213 bool terminationEnabled, terminatePending;
214#endif // Q_OS_WIN
215#ifdef Q_OS_WASM
216 static int idealThreadCount;
217#endif
219
220 static QAbstractEventDispatcher *createEventDispatcher(QThreadData *data);
221
222 void ref()
223 {
224 quitLockRef.ref();
225 }
226
227 void deref()
228 {
229 if (!quitLockRef.deref() && running) {
230 QCoreApplication::instance()->postEvent(q_ptr, new QEvent(QEvent::Quit));
231 }
232 }
233
235 {
236 return m_statusOrPendingObjects.bindingStatus();
237 }
238
239 /* Returns nullptr if the object has been added, or the binding status
240 if that one has been set in the meantime
241 */
242 QBindingStatus *addObjectWithPendingBindingStatusChange(QObject *obj);
243 void removeObjectWithPendingBindingStatusChange(QObject *obj);
244
245 // manipulating m_statusOrPendingObjects requires mutex to be locked
246 QtPrivate::BindingStatusOrList m_statusOrPendingObjects = {};
247#ifndef Q_OS_INTEGRITY
248private:
249 // Used in QThread(Private)::start to avoid racy access to QObject::objectName,
250 // unset afterwards. On INTEGRITY we set the thread name before starting it.
251 QString objectName;
252#endif
253};
254
255#else // QT_CONFIG(thread)
256
280
281#endif // QT_CONFIG(thread)
282
284{
285public:
286 QThreadData(int initialRefCount = 1);
287 ~QThreadData();
288
289 static Q_AUTOTEST_EXPORT QThreadData *current(bool createIfNecessary = true);
290 static void clearCurrentThreadData();
292 { Q_ASSERT_X(thread != nullptr, "QThread", "internal error"); return thread->d_func()->data; }
293
294
295 void ref();
296 void deref();
297 inline bool hasEventDispatcher() const
298 { return eventDispatcher.loadRelaxed() != nullptr; }
307
309 {
311 return canWait;
312 }
313
314private:
315 QAtomicInt _ref;
316
317public:
320
321 QStack<QEventLoop *> eventLoops;
323 QAtomicPointer<QThread> thread;
324 QAtomicPointer<void> threadId;
325 QAtomicPointer<QAbstractEventDispatcher> eventDispatcher;
326 QList<void *> tls;
327
332};
333
335{
336 QThreadData *threadData;
337public:
340};
341
342// thread wrapper for the main() thread
344{
345 Q_DECLARE_PRIVATE(QThread)
346
347public:
348 QAdoptedThread(QThreadData *data = nullptr);
350 void init();
351
352private:
353#if QT_CONFIG(thread)
354 void run() override;
355#endif
356};
357
359
360#endif // QTHREAD_P_H
QAdoptedThread(QThreadData *data=nullptr)
Definition qthread.cpp:124
\inmodule QtCore
Definition qatomic.h:112
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.
\inmodule QtCore
Definition qeventloop.h:16
\inmodule QtCore
Definition qcoreevent.h:45
Definition qlist.h:75
iterator insert(qsizetype i, parameter_type t)
Definition qlist.h:488
void append(parameter_type t)
Definition qlist.h:458
\inmodule QtCore
Definition qmutex.h:313
\inmodule QtCore
Definition qmutex.h:281
\inmodule QtCore
Definition qobject.h:103
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.cpp:152
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static Q_AUTOTEST_EXPORT QThreadData * current(bool createIfNecessary=true)
Definition qthread.cpp:1087
QStack< QEventLoop * > eventLoops
Definition qthread_p.h:321
QAtomicPointer< QAbstractEventDispatcher > eventDispatcher
Definition qthread_p.h:325
QThreadData(int initialRefCount=1)
Definition qthread.cpp:48
bool requiresCoreApplication
Definition qthread_p.h:331
void deref()
Definition qthread.cpp:105
static void clearCurrentThreadData()
Definition qthread.cpp:1103
bool isAdopted
Definition qthread_p.h:330
QAtomicPointer< void > threadId
Definition qthread_p.h:324
static QThreadData * get2(QThread *thread)
Definition qthread_p.h:291
QAbstractEventDispatcher * ensureEventDispatcher()
Definition qthread_p.h:300
QPostEventList postEventList
Definition qthread_p.h:322
bool canWaitLocked()
Definition qthread_p.h:308
bool hasEventDispatcher() const
Definition qthread_p.h:297
void ref()
Definition qthread.cpp:97
QAtomicPointer< QThread > thread
Definition qthread_p.h:323
QList< void * > tls
Definition qthread_p.h:326
QAbstractEventDispatcher * createEventDispatcher()
Definition qthread.cpp:113
static void setCurrentThread(QThread *)
Definition qthread_p.h:272
static QAbstractEventDispatcher * createEventDispatcher(QThreadData *data)
QThreadPrivate(QThreadData *d=nullptr)
Definition qthread.cpp:1120
void removeObjectWithPendingBindingStatusChange(QObject *)
Definition qthread_p.h:270
QThreadData * data
Definition qthread_p.h:264
QBindingStatus * m_bindingStatus
Definition qthread_p.h:265
QBindingStatus * bindingStatus()
Definition qthread_p.h:268
QBindingStatus * addObjectWithPendingBindingStatusChange(QObject *)
Definition qthread_p.h:269
virtual void run()
Definition qthread.cpp:986
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)
Combined button and popup list for selecting options.
\macro QT_NO_KEYWORDS >
Definition qcompare.h:63
void * HANDLE
#define Q_LIKELY(x)
static Q_CONSTINIT QBasicAtomicInt running
static ControlElement< T > * ptr(QWidget *widget)
GLuint64 GLenum void * handle
GLboolean r
[2]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint start
GLint ref
GLint first
struct _cl_event * event
GLhandleARB obj
[2]
GLfloat GLfloat p
[1]
static Q_CONSTINIT thread_local QBindingStatus bindingStatus
#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:158
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS)
Definition qtypeinfo.h:180
size_t quintptr
Definition qtypes.h:167
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
QObject::connect nullptr
QMutex mutex
[2]