1.static QThread *currentThread();
QThread *QThread::currentThread()
{
QThreadData *data = QThreadData::current();
Q_ASSERT(data != 0);
return data->thread.loadAcquire();
}
Type loadAcquire() const noexcept { return Ops::loadAcquire(_q_value); }
返回当前线程的指针。
2.static Qt::HANDLE currentThreadId() noexcept Q_DECL_PURE_FUNCTION;
Qt::HANDLE QThread::currentThreadId() noexcept
{
// requires a C cast here otherwise we run into trouble on AIX
return to_HANDLE(pthread_self());
}
template <typename T>
static typename std::enable_if<QTypeInfo<T>::isIntegral, Qt::HANDLE>::type to_HANDLE(T id)
{
return reinterpret_cast<Qt::HANDLE>(static_cast<intptr_t>(id));
}
3.bool event(QEvent *event) override;
bool QThread::event(QEvent *event)
{
if (event->type() == QEvent::Quit) {
quit();
return true;
} else {
return QObject::event(event);
}
}
如果是QEvent::Quit事件,则退出线程。
4.int exec();
int QThread::exec()
{
Q_D(QThread);
QMutexLocker locker(&d->mutex);
d->data->quitNow = false;
if (d->exited) {
d->exited = false;
return d->returnCode;
}
locker.unlock();
QEventLoop eventLoop;
int returnCode = eventLoop.exec();
locker.relock();
d->exited = false;
d->returnCode = -1;
return returnCode;
}
int QEventLoop::exec(ProcessEventsFlags flags)
{
Q_D(QEventLoop);
//we need to protect from race condition with QThread::exit
QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread.loadAcquire()))->mutex);
if (d->threadData->quitNow)
return -1;
if (d->inExec) {
qWarning("QEventLoop::exec: instance %p has already called exec()", this);
return -1;
}
struct LoopReference {
QEventLoopPrivate *d;
QMutexLocker &locker;
bool exceptionCaught;
LoopReference(QEventLoopPrivate *d, QMutexLocker &locker) : d(d), locker(locker), exceptionCaught(true)
{
d->inExec = true;
d->exit.storeRelease(false);
++d->threadData->loopLevel;
d->threadData->eventLoops.push(d->q_func());
locker.unlock();
}
~LoopReference()
{
if (exceptionCaught) {
qWarning("Qt has caught an exception thrown from an event handler. Throwing\n"
"exceptions from an event handler is not supported in Qt.\n"
"You must not let any exception whatsoever propagate through Qt code.\n"
"If that is not possible, in Qt 5 you must at least reimplement\n"
"QCoreApplication::notify() and catch all exceptions there.\n");
}
locker.relock();
QEventLoop *eventLoop = d->threadData->eventLoops.pop();
Q_ASSERT_X(eventLoop == d->q_func(), "QEventLoop::exec()", "internal error");
Q_UNUSED(eventLoop); // --release warning
d->inExec = false;
--d->threadData->loopLevel;
}
};
LoopReference ref(d, locker);
// remove posted quit events when entering a new event loop
QCoreApplication *app = QCoreApplication::instance();
if (app && app->thread() == thread())
QCoreApplication::removePostedEvents(app, QEvent::Quit);
#ifdef Q_OS_WASM
// Partial support for nested event loops: Make the runtime throw a JavaSrcript
// exception, which returns control to the browser while preserving the C++ stack.
// Event processing then continues as normal. The sleep call below never returns.
// QTBUG-70185
if (d->threadData->loopLevel > 1)
emscripten_sleep(1);
#endif
while (!d->exit.loadAcquire())
processEvents(flags | WaitForMoreEvents | EventLoopExec);
ref.exceptionCaught = false;
return d->returnCode.loadRelaxed();
}
进入消息循环,直到exit() 被调用。
|