7#include <private/qfieldlist_p.h>
8#include <private/qtqmlglobal_p.h>
10#include <QtCore/qmutex.h>
11#include <QtCore/qthread.h>
12#include <QtCore/qcoreevent.h>
13#include <QtCore/qwaitcondition.h>
14#include <QtCore/qcoreapplication.h>
21
22
23
24
26class QQmlThreadPrivate :
public QThread
29 struct ThreadObject :
public QObject
31 ThreadObject(QQmlThreadPrivate *p);
32 bool event(QEvent *e) override;
36 QQmlThreadPrivate(QQmlThread *);
39 inline void lock() { _mutex.lock(); }
40 inline void unlock() { _mutex.unlock(); }
41 inline void wait() { _wait.wait(&_mutex); }
42 inline void wakeOne() { _wait.wakeOne(); }
44 bool m_threadProcessing =
false;
45 bool m_mainProcessing =
false;
46 bool m_mainThreadWaiting =
false;
47 bool m_shutdown =
false;
49 typedef QFieldList<QQmlThread::Message, &QQmlThread::Message::next> MessageList;
50 MessageList threadList;
53 QQmlThread::Message *mainSync =
nullptr;
54 ThreadObject m_threadObject;
56 void triggerMainEvent();
57 void triggerThreadEvent();
63 bool event(QEvent *) override;
79 QCoreApplication::postEvent(
this,
new QEvent(QEvent::User));
86 QCoreApplication::postEvent(&m_threadObject,
new QEvent(QEvent::User));
91 if (e->type() == QEvent::User)
93 return QObject::event(e);
98 setObjectName(QStringLiteral(
"QQmlThread"));
101 setStackSize(8 * 1024 * 1024);
106 if (e->type() == QEvent::User)
108 return QThread::event(e);
115 m_mainProcessing =
true;
117 while (!mainList.isEmpty() || mainSync) {
118 bool isSync = mainSync !=
nullptr;
119 QQmlThread::Message *message = isSync?mainSync:mainList.takeFirst();
133 m_mainProcessing =
false;
143 if (!threadList.isEmpty()) {
144 m_threadProcessing =
true;
146 QQmlThread::Message *message = threadList.first();
154 delete threadList.takeFirst();
158 m_threadProcessing =
false;
178
179
180
183 Q_ASSERT(!d->m_shutdown);
185 d->m_threadObject.moveToThread(d);
195 Q_ASSERT(!d->m_shutdown);
196 d->m_shutdown =
true;
206 d->m_shutdown =
false;
231 return d->isCurrentThread();
237 return d->thread()->isCurrentThread();
242 return const_cast<QThread *>(
static_cast<
const QThread *>(d));
246
247
248
249
252 return &d->m_threadObject;
255void QQmlThread::internalCallMethodInThread(Message *message)
259 Q_ASSERT(d->m_mainThreadWaiting ==
false);
261 bool wasEmpty = d->threadList.isEmpty();
262 d->threadList.append(message);
263 if (wasEmpty && d->m_threadProcessing ==
false)
264 d->triggerThreadEvent();
266 d->m_mainThreadWaiting =
true;
275 d->mainSync =
nullptr;
280 }
while (d->mainSync || !d->threadList.isEmpty());
282 d->m_mainThreadWaiting =
false;
287
288
289
290
291
292
293void QQmlThread::internalCallMethodInMain(Message *message)
298 Q_ASSERT(d->mainSync ==
nullptr);
299 d->mainSync = message;
301 if (d->m_mainThreadWaiting) {
303 }
else if (d->m_mainProcessing) {
306 d->triggerMainEvent();
309 while (d->mainSync) {
312 d->mainSync =
nullptr;
321void QQmlThread::internalPostMethodToThread(Message *message)
325 bool wasEmpty = d->threadList.isEmpty();
326 d->threadList.append(message);
327 if (wasEmpty && d->m_threadProcessing ==
false)
328 d->triggerThreadEvent();
332void QQmlThread::internalPostMethodToMain(Message *message)
336 bool wasEmpty = d->mainList.isEmpty();
337 d->mainList.append(message);
338 if (wasEmpty && d->m_mainProcessing ==
false)
339 d->triggerMainEvent();
344
345
346
347
348
349
350
351
352
353
357 Q_ASSERT(d->m_mainThreadWaiting ==
false);
359 d->m_mainThreadWaiting =
true;
361 if (d->mainSync || !d->threadList.isEmpty()) {
368 d->mainSync =
nullptr;
375 d->m_mainThreadWaiting =
false;
379
380
381
382
383
384
388 if (Message *mainSync = std::exchange(d->mainSync,
nullptr))
390 while (!d->mainList.isEmpty())
391 delete d->mainList.takeFirst();
392 while (!d->threadList.isEmpty())
393 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(liburing)