6#include <private/qfieldlist_p.h>
7#include <private/qtqmlglobal_p.h>
9#include <QtCore/qmutex.h>
10#include <QtCore/qthread.h>
11#include <QtCore/qcoreevent.h>
12#include <QtCore/qwaitcondition.h>
13#include <QtCore/qcoreapplication.h>
20
21
22
23
25class QQmlThreadPrivate :
public QThread
28 struct ThreadObject :
public QObject
30 ThreadObject(QQmlThreadPrivate *p);
31 bool event(QEvent *e) override;
35 QQmlThreadPrivate(QQmlThread *);
38 inline void lock() { _mutex.lock(); }
39 inline void unlock() { _mutex.unlock(); }
40 inline void wait() { _wait.wait(&_mutex); }
41 inline void wakeOne() { _wait.wakeOne(); }
43 bool m_threadProcessing =
false;
44 bool m_mainProcessing =
false;
45 bool m_mainThreadWaiting =
false;
46 bool m_shutdown =
false;
48 typedef QFieldList<QQmlThread::Message, &QQmlThread::Message::next> MessageList;
49 MessageList threadList;
52 QQmlThread::Message *mainSync =
nullptr;
53 ThreadObject m_threadObject;
55 void triggerMainEvent();
56 void triggerThreadEvent();
62 bool event(QEvent *) override;
78 QCoreApplication::postEvent(
this,
new QEvent(QEvent::User));
85 QCoreApplication::postEvent(&m_threadObject,
new QEvent(QEvent::User));
90 if (e->type() == QEvent::User)
92 return QObject::event(e);
97 setObjectName(QStringLiteral(
"QQmlThread"));
100 setStackSize(8 * 1024 * 1024);
105 if (e->type() == QEvent::User)
107 return QThread::event(e);
114 m_mainProcessing =
true;
116 while (!mainList.isEmpty() || mainSync) {
117 bool isSync = mainSync !=
nullptr;
118 QQmlThread::Message *message = isSync?mainSync:mainList.takeFirst();
132 m_mainProcessing =
false;
142 if (!threadList.isEmpty()) {
143 m_threadProcessing =
true;
145 QQmlThread::Message *message = threadList.first();
153 delete threadList.takeFirst();
157 m_threadProcessing =
false;
177
178
179
182 Q_ASSERT(!d->m_shutdown);
184 d->m_threadObject.moveToThread(d);
194 Q_ASSERT(!d->m_shutdown);
195 d->m_shutdown =
true;
205 d->m_shutdown =
false;
230 return d->isCurrentThread();
236 return d->thread()->isCurrentThread();
241 return const_cast<QThread *>(
static_cast<
const QThread *>(d));
245
246
247
248
251 return &d->m_threadObject;
254void QQmlThread::internalCallMethodInThread(Message *message)
258 Q_ASSERT(d->m_mainThreadWaiting ==
false);
260 bool wasEmpty = d->threadList.isEmpty();
261 d->threadList.append(message);
262 if (wasEmpty && d->m_threadProcessing ==
false)
263 d->triggerThreadEvent();
265 d->m_mainThreadWaiting =
true;
274 d->mainSync =
nullptr;
279 }
while (d->mainSync || !d->threadList.isEmpty());
281 d->m_mainThreadWaiting =
false;
286
287
288
289
290
291
292void QQmlThread::internalCallMethodInMain(Message *message)
297 Q_ASSERT(d->mainSync ==
nullptr);
298 d->mainSync = message;
300 if (d->m_mainThreadWaiting) {
302 }
else if (d->m_mainProcessing) {
305 d->triggerMainEvent();
308 while (d->mainSync) {
311 d->mainSync =
nullptr;
320void QQmlThread::internalPostMethodToThread(Message *message)
324 bool wasEmpty = d->threadList.isEmpty();
325 d->threadList.append(message);
326 if (wasEmpty && d->m_threadProcessing ==
false)
327 d->triggerThreadEvent();
331void QQmlThread::internalPostMethodToMain(Message *message)
335 bool wasEmpty = d->mainList.isEmpty();
336 d->mainList.append(message);
337 if (wasEmpty && d->m_mainProcessing ==
false)
338 d->triggerMainEvent();
343
344
345
346
347
348
349
350
351
352
356 Q_ASSERT(d->m_mainThreadWaiting ==
false);
358 d->m_mainThreadWaiting =
true;
360 if (d->mainSync || !d->threadList.isEmpty()) {
367 d->mainSync =
nullptr;
374 d->m_mainThreadWaiting =
false;
378
379
380
381
382
383
387 if (Message *mainSync = std::exchange(d->mainSync,
nullptr))
389 while (!d->mainList.isEmpty())
390 delete d->mainList.takeFirst();
391 while (!d->threadList.isEmpty())
392 delete d->threadList.takeFirst();
QQmlThreadPrivate(QQmlThread *q)
QFieldList< QQmlThread::Message, &QQmlThread::Message::next > MessageList
bool event(QEvent *e) override
This virtual function receives events to an object and should return true if the event e was recogniz...
bool isThisThread() const
void waitForNextMessage()
bool isParentThread() const
QObject * threadObject() const
QT_REQUIRE_CONFIG(thread)