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>
19class QQmlThreadPrivate :
public QThread
22 struct ThreadObject :
public QObject
24 ThreadObject(QQmlThreadPrivate *p);
25 bool event(QEvent *e) override;
29 QQmlThreadPrivate(QQmlThread *);
32 inline void lock() { _mutex.lock(); }
33 inline void unlock() { _mutex.unlock(); }
34 inline void wait() { _wait.wait(&_mutex); }
35 inline void wakeOne() { _wait.wakeOne(); }
37 bool m_threadProcessing =
false;
38 bool m_mainProcessing =
false;
39 bool m_mainThreadWaiting =
false;
40 bool m_shutdown =
false;
42 typedef QFieldList<QQmlThread::Message, &QQmlThread::Message::next> MessageList;
43 MessageList threadList;
46 QQmlThread::Message *mainSync =
nullptr;
47 ThreadObject m_threadObject;
49 void triggerMainEvent();
50 void triggerThreadEvent();
56 bool event(QEvent *) override;
72 QCoreApplication::postEvent(
this,
new QEvent(QEvent::User));
79 QCoreApplication::postEvent(&m_threadObject,
new QEvent(QEvent::User));
84 if (e->type() == QEvent::User)
86 return QObject::event(e);
91 setObjectName(QStringLiteral(
"QQmlThread"));
94 setStackSize(8 * 1024 * 1024);
99 if (e->type() == QEvent::User)
101 return QThread::event(e);
108 m_mainProcessing =
true;
110 while (!mainList.isEmpty() || mainSync) {
111 bool isSync = mainSync !=
nullptr;
112 QQmlThread::Message *message = isSync?mainSync:mainList.takeFirst();
126 m_mainProcessing =
false;
136 if (!threadList.isEmpty()) {
137 m_threadProcessing =
true;
139 QQmlThread::Message *message = threadList.first();
147 delete threadList.takeFirst();
151 m_threadProcessing =
false;
171
172
173
176 Q_ASSERT(!d->m_shutdown);
178 d->m_threadObject.moveToThread(d);
188 Q_ASSERT(!d->m_shutdown);
189 d->m_shutdown =
true;
199 d->m_shutdown =
false;
224 return d->isCurrentThread();
230 return d->thread()->isCurrentThread();
235 return const_cast<QThread *>(
static_cast<
const QThread *>(d));
239
240
243 return &d->m_threadObject;
246void QQmlThread::internalCallMethodInThread(Message *message)
250 Q_ASSERT(d->m_mainThreadWaiting ==
false);
252 bool wasEmpty = d->threadList.isEmpty();
253 d->threadList.append(message);
254 if (wasEmpty && d->m_threadProcessing ==
false)
255 d->triggerThreadEvent();
257 d->m_mainThreadWaiting =
true;
266 d->mainSync =
nullptr;
271 }
while (d->mainSync || !d->threadList.isEmpty());
273 d->m_mainThreadWaiting =
false;
278
279
280
281
282
283
284void QQmlThread::internalCallMethodInMain(Message *message)
289 Q_ASSERT(d->mainSync ==
nullptr);
290 d->mainSync = message;
292 if (d->m_mainThreadWaiting) {
294 }
else if (d->m_mainProcessing) {
297 d->triggerMainEvent();
300 while (d->mainSync) {
303 d->mainSync =
nullptr;
312void QQmlThread::internalPostMethodToThread(Message *message)
316 bool wasEmpty = d->threadList.isEmpty();
317 d->threadList.append(message);
318 if (wasEmpty && d->m_threadProcessing ==
false)
319 d->triggerThreadEvent();
323void QQmlThread::internalPostMethodToMain(Message *message)
327 bool wasEmpty = d->mainList.isEmpty();
328 d->mainList.append(message);
329 if (wasEmpty && d->m_mainProcessing ==
false)
330 d->triggerMainEvent();
335
336
337
338
339
340
341
342
343
344
348 Q_ASSERT(d->m_mainThreadWaiting ==
false);
350 d->m_mainThreadWaiting =
true;
352 if (d->mainSync || !d->threadList.isEmpty()) {
359 d->mainSync =
nullptr;
366 d->m_mainThreadWaiting =
false;
370
371
372
373
374
375
379 if (Message *mainSync = std::exchange(d->mainSync,
nullptr))
381 while (!d->mainList.isEmpty())
382 delete d->mainList.takeFirst();
383 while (!d->threadList.isEmpty())
384 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
And object living in the QML thread, in case you want to parent other objects to it.
QT_REQUIRE_CONFIG(thread)