QT(5):主线程和事件循环

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

QT(5):主线程和事件循环_第1张图片

一、在QCoreApplication::QCoreApplication()中创建事件调度器

QCoreApplication::QCoreApplication(int &argc, char **argv
#ifndef Q_QDOC
                                   , int _internal
#endif
                                   )
#ifdef QT_NO_QOBJECT
    : d_ptr(new QCoreApplicationPrivate(argc, argv, _internal))
#else
    : QObject(*new QCoreApplicationPrivate(argc, argv, _internal))
#endif
{
    d_func()->q_ptr = this;
    d_func()->init();
#ifndef QT_NO_QOBJECT
    QCoreApplicationPrivate::eventDispatcher->startingUp();
#endif
}
void QCoreApplicationPrivate::init()
{

#ifndef QT_NO_QOBJECT
    // use the event dispatcher created by the app programmer (if any)
    Q_ASSERT(!eventDispatcher);
//检查用户是否自行创建了事件调度器,没有则创建---------------------------------------------------
    eventDispatcher = threadData->eventDispatcher.loadRelaxed();
//创建事件调度器-----------------------------------------------------------------
    // otherwise we create one
    if (!eventDispatcher)
        createEventDispatcher();
    Q_ASSERT(eventDispatcher);
//事件调度器是否有父对象,没有则把q指针作为父对象---------------------------------------
//movetothread,将事件调度器的槽函数放在子线程中,构造函数仍在主线程---------------------------------------
    if (!eventDispatcher->parent()) {
        eventDispatcher->moveToThread(threadData->thread.loadAcquire());
        eventDispatcher->setParent(q);
    }
//重置当前线程的事件调度器,处于准备状态------------------------------------------------------
    threadData->eventDispatcher = eventDispatcher;
    eventDispatcherReady();
#endif
//处理命令行参数------------------------------------------------------------------------------
    processCommandLineArguments();
//启动hook------------------------------------------------------------------------------
    qt_call_pre_routines();
    qt_startup_hook();
#ifndef QT_BOOTSTRAPPED
    if (Q_UNLIKELY(qtHookData[QHooks::Startup]))
        reinterpret_cast<QHooks::StartupCallback>(qtHookData[QHooks::Startup])();
#endif

#ifndef QT_NO_QOBJECT
    is_app_running = true; // No longer starting up.
#endif
}
void QCoreApplicationPrivate::createEventDispatcher()
{
//获取当前线程的线程数据-----------------------------------------------------------------------
    Q_Q(QCoreApplication);
    QThreadData *data = QThreadData::current();
    Q_ASSERT(!data->hasEventDispatcher());
//调用QThreadPrivate::createEventDispatcher创建事件调度器并设置其父对象----------------------------
    eventDispatcher = data->createEventDispatcher();
    eventDispatcher->setParent(q);
}
QAbstractEventDispatcher *QThreadData::createEventDispatcher()
{
//调用QThreadPrivate::createEventDispatcher创建-------------------------------------
    QAbstractEventDispatcher *ed = QThreadPrivate::createEventDispatcher(this);
    eventDispatcher.storeRelease(ed);
//创建完后启动----------------------------------------------------------------------------
    ed->startingUp();
    return ed;
}
QAbstractEventDispatcher *QThreadPrivate::createEventDispatcher(QThreadData *data)
{
    Q_UNUSED(data);
#ifndef Q_OS_WINRT
    return new QEventDispatcherWin32;
#else
    return new QEventDispatcherWinRT;
#endif
}

二、在QCoreApplication::exec()中创建事件循环器

int QCoreApplication::exec()
{
//检查QCoreApplication自身实例是否存在
    if (!QCoreApplicationPrivate::checkInstance("exec"))
        return -1;
//获取实例d指针的线程数据,检查QCoreApplication是否位于主线程中
    QThreadData *threadData = self->d_func()->threadData;
    if (threadData != QThreadData::current()) {
        qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className());
        return -1;
    }
//检查主线程中是否存在事件循环
    if (!threadData->eventLoops.isEmpty()) {
        qWarning("QCoreApplication::exec: The event loop is already running");
        return -1;
    }
//没有则创建
    threadData->quitNow = false;
    QEventLoop eventLoop;
    self->d_func()->in_exec = true;
    self->d_func()->aboutToQuitEmitted = false;
    int returnCode = eventLoop.exec();
    threadData->quitNow = false;

    if (self)
        self->d_func()->execCleanup();

    return returnCode;
}

QEventLoop::exec()将创建的事件循环器添加到主线程中,为主线程的主循环器,负责gui的操作事件

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;//循环器级别调至1级
            d->threadData->eventLoops.push(d->q_func());//将事件循环器添加到所在线程的事件循环器存储容器中
            locker.unlock();
        }

        ~LoopReference()
        {//*****有省略********* }
         //*****有省略*********  
    };
    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);//如果是则清除程序退出的post事件

 //*****有省略*********  
//如果没有退出,执行进程事件
    while (!d->exit.loadAcquire())
        processEvents(flags | WaitForMoreEvents | EventLoopExec);

    ref.exceptionCaught = false;
    return d->returnCode.loadRelaxed();
}

QEventLoop::processEvents进程事件中检查事件调度器(eventdispatcherwin32)是否存在,如果不存在则退出,存在则调用eventDispatcher的processEvents处理程序所有事件。

bool QEventLoop::processEvents(ProcessEventsFlags flags)
{
    Q_D(QEventLoop);
    if (!d->threadData->hasEventDispatcher())
        return false;
    return d->threadData->eventDispatcher.loadRelaxed()->processEvents(flags);
}

调度器eventdispatcherwin32作用是qt系统和windows系统进行数据交互。

bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
{
    Q_D(QEventDispatcherWin32);
//检查private对象是否创建了隐藏窗口,如果没有则进行创建,并唤醒
    if (!d->internalHwnd) {
        createInternalHwnd();
        wakeUp(); // trigger a call to sendPostedEvents()
    }

    d->interrupt.storeRelaxed(false);
    emit awake();//发送已创建信号

    sendPostedEvents();

    bool canWait;
    bool retVal = false;
    do {
        DWORD waitRet = 0;
        DWORD nCount = 0;
        HANDLE *pHandles = nullptr;
 //检查windows事件通知激活事件的状态,如果为激活状态,则获取状态的句柄
        if (d->winEventNotifierActivatedEvent) {
            nCount = 1;
            pHandles = &d->winEventNotifierActivatedEvent;
        }
        QVarLengthArray<MSG> processedTimers;
        while (!d->interrupt.loadRelaxed()) {
            MSG msg;
            bool haveMessage;
//检查用户输入事件的队列是否为空,不为空则处理第一个事件
            if (!(flags & QEventLoop::ExcludeUserInputEvents) && !d->queuedUserInputEvents.isEmpty()) {
                // process queued user input events
                haveMessage = true;
                msg = d->queuedUserInputEvents.takeFirst();
 //检查socket事件的队列是否为空,不为空则处理第一个事件
            } else if(!(flags & QEventLoop::ExcludeSocketNotifiers) && !d->queuedSocketEvents.isEmpty()) {
                // process queued socket events
                haveMessage = true;
                msg = d->queuedSocketEvents.takeFirst();
//检查事件可用性,如果可用,移除后进行转化,重新加入到队列中
            } else {
                haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE);
                if (haveMessage) {
                
                    if (flags.testFlag(QEventLoop::ExcludeUserInputEvents)
                        && isUserInputMessage(msg.message)) {
                        // queue user input events for later processing
                        d->queuedUserInputEvents.append(msg);
                        continue;
                    }
                    if ((flags & QEventLoop::ExcludeSocketNotifiers)
                        && (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) {
                        // queue socket events for later processing
                        d->queuedSocketEvents.append(msg);
                        continue;
                    }
                }
            }
//事件无效,进行相应处理
            if (!haveMessage) {
                // no message - check for signalled objects
                waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, 0, QS_ALLINPUT, MWMO_ALERTABLE);
                if ((haveMessage = (waitRet == WAIT_OBJECT_0 + nCount))) {
                    // a new message has arrived, process it
                    continue;
                }
            }
//事件有效,获取勾子事件,进行数据的传递,即事件转发给windows系统
            if (haveMessage) {
                if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) {
                    // Set result to 'true', if the message was sent by wakeUp().
                    if (msg.wParam == WMWP_QT_FROMWAKEUP)
                        retVal = true;
                    continue;
                }
                if (msg.message == WM_TIMER) {
                    // avoid live-lock by keeping track of the timers we've already sent
                    bool found = false;
                    for (int i = 0; !found && i < processedTimers.count(); ++i) {
                        const MSG processed = processedTimers.constData()[i];
                        found = (processed.wParam == msg.wParam && processed.hwnd == msg.hwnd && processed.lParam == msg.lParam);
                    }
                    if (found)
                        continue;
                    processedTimers.append(msg);
                } else if (msg.message == WM_QUIT) {
                    if (QCoreApplication::instance())
                        QCoreApplication::instance()->quit();
                    return false;
                }

                if (!filterNativeEvent(QByteArrayLiteral("windows_generic_MSG"), &msg, 0)) {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
            } else if (waitRet - WAIT_OBJECT_0 < nCount) {
                activateEventNotifiers();
            } else {
                // nothing todo so break
                break;
            }
            retVal = true;
        }

        // still nothing - wait for message or signalled objects
        canWait = (!retVal
                   && !d->interrupt.loadRelaxed()
                   && (flags & QEventLoop::WaitForMoreEvents));
        if (canWait) {
            emit aboutToBlock();
            waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
            emit awake();
            if (waitRet - WAIT_OBJECT_0 < nCount) {
                activateEventNotifiers();
                retVal = true;
            }
        }
    } while (canWait);

    return retVal;
}


QEventDispatcherWin32::createInternalHwnd()创建隐藏窗口,通过hook将事件数据转发给windows系统,同时通过qt_internal_pro获取windows系统反馈的数据信息,解包后分发处理

void QEventDispatcherWin32::createInternalHwnd()
{
    Q_D(QEventDispatcherWin32);

    if (d->internalHwnd)
        return;
    d->internalHwnd = qt_create_internal_window(this);

    // setup GetMessage hook needed to drive our posted events
    d->getMessageHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC) qt_GetMessageHook, NULL, GetCurrentThreadId());
    if (Q_UNLIKELY(!d->getMessageHook)) {
        int errorCode = GetLastError();
        qFatal("Qt: INTERNAL ERROR: failed to install GetMessage hook: %d, %ls",
               errorCode, qUtf16Printable(qt_error_string(errorCode)));
    }

    // start all normal timers
    for (int i = 0; i < d->timerVec.count(); ++i)
        d->registerTimer(d->timerVec.at(i));
}

qt_create_internal_window函数中创建了QWindowsMessageWindowClassContext 类消息上下文对象ctx,创建隐藏窗口

static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher)
{//
    QWindowsMessageWindowClassContext *ctx = qWindowsMessageWindowClassContext();
    if (!ctx->atom)
        return 0;
    HWND wnd = CreateWindow(ctx->className,    // classname
                            ctx->className,    // window name
                            0,                 // style
                            0, 0, 0, 0,        // geometry
                            HWND_MESSAGE,            // parent
                            0,                 // menu handle
                            GetModuleHandle(0),     // application
                            0);                // windows creation data.

   //*****有省略**************************************

    return wnd;
}

上下文类中调用回调函数qt_internal_poc,获取windows系统传给qt的msg消息,并进行解析,之后传递给qt系统进行相应的类型判断,并作出相应

QWindowsMessageWindowClassContext::QWindowsMessageWindowClassContext()
    : atom(0), className(0)
{
    // make sure that multiple Qt's can coexist in the same process
    const QString qClassName = QStringLiteral("QEventDispatcherWin32_Internal_Widget")
        + QString::number(quintptr(qt_internal_proc));
    //*****有省略**************************************
}

createInternalHwnd()中的setwindowsHookEx监听主线程的所有事件,第二个参数是函数qt_GetMessageHook,通过Windows的原生消息接口PostMessage将消息传递给创建的隐藏窗口,从而将消息传给windows系统

LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp)
{
    QEventDispatcherWin32 *q = qobject_cast<QEventDispatcherWin32 *>(QAbstractEventDispatcher::instance());
    Q_ASSERT(q != 0);
    QEventDispatcherWin32Private *d = q->d_func();
    MSG *msg = reinterpret_cast<MSG *>(lp);
    static const UINT mask = inputQueueMask();

    if (HIWORD(GetQueueStatus(mask)) == 0 && wp == PM_REMOVE) {
        // Allow posting WM_QT_SENDPOSTEDEVENTS message.
        d->wakeUps.storeRelaxed(0);
        if (!(msg->hwnd == d->internalHwnd && msg->message == WM_QT_SENDPOSTEDEVENTS)) {
            PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS,
                        WMWP_QT_TOFOREIGNLOOP, 0);
        }
    }
    return d->getMessageHook ? CallNextHookEx(0, code, wp, lp) : 0;
}

你可能感兴趣的:(QT,qt,开发语言)