QEventLoop源码

2023-11-06

/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qeventloop.h"

#include "qabstracteventdispatcher.h"
#include "qcoreapplication.h"
#include "qcoreapplication_p.h"
#include "qelapsedtimer.h"

#include "qobject_p.h"
#include "qeventloop_p.h"
#include <private/qthread_p.h>

QT_BEGIN_NAMESPACE

/*!
    \class QEventLoop
    \inmodule QtCore
    \brief The QEventLoop class provides a means of entering and leaving an event loop.

    At any time, you can create a QEventLoop object and call exec()
    on it to start a local event loop. From within the event loop,
    calling exit() will force exec() to return.

    \sa QAbstractEventDispatcher
*/

/*!
    \enum QEventLoop::ProcessEventsFlag

    This enum controls the types of events processed by the
    processEvents() functions.

    \value AllEvents All events. Note that
    \l{QEvent::DeferredDelete}{DeferredDelete} events are processed
    specially. See QObject::deleteLater() for more details.

    \value ExcludeUserInputEvents Do not process user input events,
    such as ButtonPress and KeyPress. Note that the events are not
    discarded; they will be delivered the next time processEvents() is
    called without the ExcludeUserInputEvents flag.

    \value ExcludeSocketNotifiers Do not process socket notifier
    events. Note that the events are not discarded; they will be
    delivered the next time processEvents() is called without the
    ExcludeSocketNotifiers flag.

    \value WaitForMoreEvents Wait for events if no pending events are
    available.

    \omitvalue X11ExcludeTimers
    \omitvalue EventLoopExec
    \omitvalue DialogExec

    \sa processEvents()
*/

/*!
    Constructs an event loop object with the given \a parent.
*/
QEventLoop::QEventLoop(QObject *parent)
    : QObject(*new QEventLoopPrivate, parent)
{
    Q_D(QEventLoop);
    if (!QCoreApplication::instance() && QCoreApplicationPrivate::threadRequiresCoreApplication()) {
        qWarning("QEventLoop: Cannot be used without QApplication");
    } else if (!d->threadData->eventDispatcher.load()) {
        QThreadPrivate::createEventDispatcher(d->threadData);
    }
}

/*!
    Destroys the event loop object.
*/
QEventLoop::~QEventLoop()
{ }


/*!
    Processes pending events that match \a flags until there are no
    more events to process. Returns \c true if pending events were handled;
    otherwise returns \c false.

    This function is especially useful if you have a long running
    operation and want to show its progress without allowing user
    input; i.e. by using the \l ExcludeUserInputEvents flag.

    This function is simply a wrapper for
    QAbstractEventDispatcher::processEvents(). See the documentation
    for that function for details.
*/
bool QEventLoop::processEvents(ProcessEventsFlags flags)
{
    Q_D(QEventLoop);
    if (!d->threadData->eventDispatcher.load())
        return false;
    return d->threadData->eventDispatcher.load()->processEvents(flags);
}

/*!
    Enters the main event loop and waits until exit() is called.
    Returns the value that was passed to exit().

    If \a flags are specified, only events of the types allowed by
    the \a flags will be processed.

    It is necessary to call this function to start event handling. The
    main event loop receives events from the window system and
    dispatches these to the application widgets.

    Generally speaking, no user interaction can take place before
    calling exec(). As a special case, modal widgets like QMessageBox
    can be used before calling exec(), because modal widgets
    use their own local event loop.

    To make your application perform idle processing (i.e. executing a
    special function whenever there are no pending events), use a
    QTimer with 0 timeout. More sophisticated idle processing schemes
    can be achieved using processEvents().

    \sa QCoreApplication::quit(), exit(), processEvents()
*/
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))->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);

    while (!d->exit.loadAcquire())
        processEvents(flags | WaitForMoreEvents | EventLoopExec);

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

/*!
    Process pending events that match \a flags for a maximum of \a
    maxTime milliseconds, or until there are no more events to
    process, whichever is shorter.
    This function is especially useful if you have a long running
    operation and want to show its progress without allowing user
    input, i.e. by using the \l ExcludeUserInputEvents flag.

    \b{Notes:}
    \list
    \li This function does not process events continuously; it
       returns after all available events are processed.
    \li Specifying the \l WaitForMoreEvents flag makes no sense
       and will be ignored.
    \endlist
*/
void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime)
{
    Q_D(QEventLoop);
    if (!d->threadData->eventDispatcher.load())
        return;

    QElapsedTimer start;
    start.start();
    while (processEvents(flags & ~WaitForMoreEvents)) {
        if (start.elapsed() > maxTime)
            break;
    }
}

/*!
    Tells the event loop to exit with a return code.

    After this function has been called, the event loop returns from
    the call to exec(). The exec() function returns \a returnCode.

    By convention, a \a returnCode of 0 means success, and any non-zero
    value indicates an error.

    Note that unlike the C library function of the same name, this
    function \e does return to the caller -- it is event processing that
    stops.

    \sa QCoreApplication::quit(), quit(), exec()
*/
void QEventLoop::exit(int returnCode)
{
    Q_D(QEventLoop);
    if (!d->threadData->eventDispatcher.load())
        return;

    d->returnCode.store(returnCode);
    d->exit.storeRelease(true);
    d->threadData->eventDispatcher.load()->interrupt();
}

/*!
    Returns \c true if the event loop is running; otherwise returns
    false. The event loop is considered running from the time when
    exec() is called until exit() is called.

    \sa exec(), exit()
 */
bool QEventLoop::isRunning() const
{
    Q_D(const QEventLoop);
    return !d->exit.loadAcquire();
}

/*!
    Wakes up the event loop.

    \sa QAbstractEventDispatcher::wakeUp()
*/
void QEventLoop::wakeUp()
{
    Q_D(QEventLoop);
    if (!d->threadData->eventDispatcher.load())
        return;
    d->threadData->eventDispatcher.load()->wakeUp();
}


/*!
    \reimp
*/
bool QEventLoop::event(QEvent *event)
{
    if (event->type() == QEvent::Quit) {
        quit();
        return true;
    } else {
        return QObject::event(event);
    }
}

/*!
    Tells the event loop to exit normally.

    Same as exit(0).

    \sa QCoreApplication::quit(), exit()
*/
void QEventLoop::quit()
{ exit(0); }


class QEventLoopLockerPrivate
{
public:
    explicit QEventLoopLockerPrivate(QEventLoopPrivate *loop)
      : loop(loop), type(EventLoop)
    {
        loop->ref();
    }

    explicit QEventLoopLockerPrivate(QThreadPrivate *thread)
      : thread(thread), type(Thread)
    {
        thread->ref();
    }

    explicit QEventLoopLockerPrivate(QCoreApplicationPrivate *app)
      : app(app), type(Application)
    {
        app->ref();
    }

    ~QEventLoopLockerPrivate()
    {
        switch (type)
        {
        case EventLoop:
            loop->deref();
            break;
        case Thread:
            thread->deref();
            break;
        default:
            app->deref();
            break;
        }
    }

private:
    union {
        QEventLoopPrivate * loop;
        QThreadPrivate * thread;
        QCoreApplicationPrivate * app;
    };
    enum Type {
        EventLoop,
        Thread,
        Application
    };
    const Type type;
};

/*!
    \class QEventLoopLocker
    \inmodule QtCore
    \brief The QEventLoopLocker class provides a means to quit an event loop when it is no longer needed.
    \since 5.0

    The QEventLoopLocker operates on particular objects - either a QCoreApplication
    instance, a QEventLoop instance or a QThread instance.

    This makes it possible to, for example, run a batch of jobs with an event loop
    and exit that event loop after the last job is finished. That is accomplished
    by keeping a QEventLoopLocker with each job instance.

    The variant which operates on QCoreApplication makes it possible to finish
    asynchronously running jobs after the last gui window has been closed. This
    can be useful for example for running a job which uploads data to a network.

    \sa QEventLoop, QCoreApplication
*/

/*!
    Creates an event locker operating on the QCoreApplication.

    The application will quit when there are no more QEventLoopLockers operating on it.

    \sa QCoreApplication::quit(), QCoreApplication::isQuitLockEnabled()
 */
QEventLoopLocker::QEventLoopLocker()
  : d_ptr(new QEventLoopLockerPrivate(static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance()))))
{

}

/*!
    Creates an event locker operating on the \a loop.

    This particular QEventLoop will quit when there are no more QEventLoopLockers operating on it.

    \sa QEventLoop::quit()
 */
QEventLoopLocker::QEventLoopLocker(QEventLoop *loop)
  : d_ptr(new QEventLoopLockerPrivate(static_cast<QEventLoopPrivate*>(QObjectPrivate::get(loop))))
{

}

/*!
    Creates an event locker operating on the \a thread.

    This particular QThread will quit when there are no more QEventLoopLockers operating on it.

    \sa QThread::quit()
 */
QEventLoopLocker::QEventLoopLocker(QThread *thread)
  : d_ptr(new QEventLoopLockerPrivate(static_cast<QThreadPrivate*>(QObjectPrivate::get(thread))))
{

}

/*!
    Destroys this event loop locker object
 */
QEventLoopLocker::~QEventLoopLocker()
{
    delete d_ptr;
}

QT_END_NAMESPACE

参考:

https://www.yuque.com/docs/share/ab6d4575-7b38-45c2-8316-391a444d53c5

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QEventLoop源码 的相关文章

  • LINQ to XML - 如何正确使用 XDocument

    现在我首先要说的是 这确实是一项任务 然而 在我遇到 Linq to XML 语法之前 我几乎已经完成了它 我有 2 个课程 曲目和 CD 现在作为作业的一部分 我创建了一张 CD 然后向其中添加了一些曲目 在搜索了大量完美解释了如何从 x
  • boost线程在中断时不打印退出消息

    我有这段代码用于执行三个线程 其中第二个线程应在按 Enter 时中断并打印退出消息 void input val DO STUFF return void process val DO STUFF try cout lt lt waiti
  • 实体框架代码优先 - 在另一个文件中配置

    使用 Fluent API 将表到实体的映射分开的最佳方法是什么 以便它全部位于单独的类中 而不是内联在 OnModelCreating 方法中 我目前在做什么 public class FooContext DbContext prote
  • 当我单击 GridView 项时返回 ImageView 实例

    当我点击GridView项时如何返回ImageView实例 我为 ItemClick 创建自定义绑定事件 public class ItemClickSquareBinding MvxBaseAndroidTargetBinding pri
  • __FUNCTION__ 宏的 C# 版本

    有人对 C FUNCTION 宏的 C 版本有好的解决方案吗 编译器似乎不喜欢它 尝试使用这个代替 System Reflection MethodBase GetCurrentMethod Name C 没有 LINE or FUNCTI
  • 阅读 Stack Overflow RSS 源

    我正在尝试获取未回答问题的列表the feed https stackoverflow com feeds 但我在阅读时遇到困难 const string RECENT QUESTIONS https stackoverflow com f
  • Qt中正确的线程方式

    我的图像加载非常耗时 图像很大 并且在加载时也完成了一些操作 我不想阻止应用程序 GUI 我的想法是在另一个线程中加载图像 发出图像已加载的信号 然后用该图像重绘视图 我的做法 void Window loadImage ImageLoad
  • 防止复制构造和返回值引用的分配

    如果我有一个函数返回对类实例的引用 但我无法控制其源 比如说list
  • C#:使用 System.Text 和 System.Text.RegularExpressions 之间的区别

    在 ASP NET C 应用程序中 我注意到为了使用 Regex 和 StringBuilder 我必须将两者都放在 using System Text using System Text RegularExpressions 从简单的角度
  • C#:如何使用 SHOpenFolderAndSelectItems [重复]

    这个问题在这里已经有答案了 有人可以举例说明如何使用 shell 函数吗SH打开文件夹并选择项目 http msdn microsoft com en us library bb762232 VS 85 aspx来自 C 我不太明白如何使用
  • 使用 Linq 进行异步Where过滤

    我有一个List通过填充的元素async调用 WebService 没问题 我需要过滤该列表以便在应用程序视图上显示某些内容 我试过这个 List
  • 如何使用 Clang 查找内存泄漏

    我在我的机器 ubuntu 中安装了 Clang 以便发现我的 C 代码中的内存泄漏 我编写了一个示例代码来检查它的工作情况 如下所示 File hello c for leak detection include
  • 编写专门用于类及其子类的函数模板

    我正在尝试编写一个函数模板 一个版本应该用于不满足另一版本标准的所有类型 当参数是给定类的基类或该类本身时 应使用另一个版本 我尝试过超载Base 但是当类派生自Base 他们使用通用的 而不是特定的 我也尝试过这种 SFINAE 方法 s
  • 如何从枚举中选择随机值?

    给定 C 中的任意枚举 如何选择随机值 我没有找到这个非常基本的问题 我会在一分钟内发布我的答案作为任何人的参考 但请随意发布你自己的答案 Array values Enum GetValues typeof Bar Random rand
  • 为什么我不能在扩展 List 的类中调用 OrderBy?

    我有一堂课 Deck 其中包含一个名为的方法Shuffle 我正在致力于重构Deck延长List
  • 改进C++逐行读取文件的能力?

    我正在解析大约 500GB 的日志文件 我的 C 版本需要 3 5 分钟 我的 Go 版本需要 1 2 分钟 我正在使用 C 的流来流式传输文件的每一行以进行解析 include
  • 如何使用 g++ 在 c++ 20 中使用模块?

    我读了这个链接https gcc gnu org wiki cxx modules https gcc gnu org wiki cxx modules并尝试从该网站复制以下示例 我已经知道这个编译器部分支持模块系统 注 我用的是windo
  • 有没有办法让 VS2010 在我的方法中扩展或收缩 try 块?

    我的代码有很多 try catch finally 块 与我在 VS2010 中的方法不同 除了添加区域之外 我无法在开发时扩展或收缩这些区域来隐藏内容 try vm R vm Qu vm T vm D vm Fil vm Type vm
  • 局部静态变量初始化是线程安全的[重复]

    这个问题在这里已经有答案了 假设我有一个包含三个静态函数的类 如下所示 include
  • ASP.NET Core:会话 ID 始终变化

    今天启动了一个全新的 ASP NET Core 网站 按照说明添加会话 我们在索引页上打印出会话 ID 它始终是唯一的 我认为这可能是 cookie 合规性 所以我在 Chrome 的高级设置和调试器中删除了所有 cookie 但横幅不会再

随机推荐

  • “华为杯”研究生数学建模竞赛2020年-【华为杯】B题:汽油辛烷值优化建模(附获奖论文和python代码实现)

    目录 摘 要 1 问题重述 1 1 问题背景 1 2 问题重述 2 模型假设 3 符号说明
  • 据说程序员节 随手记录下matlab的tan和atan(反正切 arctan函数)

    matlab求正切 反正切 随笔 tan函数测试 tan 0 0 tan 45 1 6198 tan pi 4 1 可以看出 matlab的输入单位是rad弧度 弧度和角度的换算单位为 1 rad 180 pi o 1o 1 pi 180
  • 黑客入门学习方法和盗号思路 别把这个想得很神秘

    大神请绕过 还有盗号的一些方法和思路 骗子太多 别上当 此文只是希望更多的人了解 更能很好的保护好自身虚拟财产 黑客 看着很神秘 其实都是普通人 工作不同而已 当然 有的很厉害的 他们智商都很高 这里不做讨论 就说说普通人如何学习这一块 入
  • JAVA系列教程

    1 Java快速教程 http www cnblogs com vamei archive 2013 03 31 2991531 html 2 Java 教程 http www runoob com java java tutorial h
  • jquery-动态添加,删除

    前言 jquery的动态添加和删除 以及显示他的数量 效果图 实现代码
  • ChatHub

    1写在前面 最近忙的不行 根本没有时间打开电脑 随着GPT 4和new bing的发布 真的可以说是AI的iphone时刻到来了 现在也是越来越多的网站接入了AI 以后人人都可以是程序员了 New Bing在GPT 4的加持下 功力大增 搜
  • 重学二、函数指针&指针运算

    目录 1 多级指针 2 数组与数组指针 3 采用指针遍历数组 4 循环时给数组赋值 5 指针类型有何用 7 函数指针 1 多级指针 int main int num 66 int pointer num 一级指针 int sec point
  • 总结:修改Anaconda中的Jupyter Notebook默认工作路径的三种方式

    总结 修改Anaconda中的Jupyter Notebook默认工作路径的三种方式 方式1 打开Windows的cmd 在cmd中输入jupyter notebook generate config如下图 可以看到路径为D Users 找
  • Qt之QTableView 获取当前选中行

    QModelIndexList list ui gt tableView gt selectedIndexes if list count lt 0 return QModelIndex index ui gt tableView gt s
  • ElasticSearch讲解——基础概念

    一 什么是ElasticSearch ElasticSearch以下简称为ES ES是一款基于Lucene的搜索服务器 它提供了一个分布式多用户能力的全文搜索引擎 并且基于RESTful web接口对外提供检索服务能力 Elasticsea
  • 展望2020

    区块链行业在2019年末迎来高光时刻 国家明确指出把区块链作为核心技术自主创新重要突破口 加快推动区块链技术和产业创新发展 新年伊始 陀螺财经邀请到数位学术圈 产业圈的相关人士 运用他们的专业知识 行业实践 剖析2020年行业的发展动向 谈
  • 【算法】链表

    算法 链表 反转链表 移除链表 交换链表 链表相交 删除链表中的倒数第N个节点 环形链表 反转链表 反转链表是指将单向链表的顺序逆转 即原本的链表方向由头节点指向尾节点 变为尾节点指向头节点 在 JavaScript 中 可以通过修改节点的
  • KEIL的下载图标是灰色的怎么办

    今天用cubemx配置好之后 generate发现下载图表是灰色的 解决方法 魔术棒下面的debug选项 有个右下角有个空手动输入 MPU
  • mock测试工具

    什么是mock测试 mock常见场景 mock常用工具 实战 1 什么是mock测试 mock测试就是对于某些不容易构造或者不容易获取的对象 用一个虚拟的对象来创建以便测试的测试方法 2 mock常见场景 1 无法控制第三方系统某接口的返回
  • PTA 7-100 敲笨钟 (20 分)(C语言版)

    微博上有个自称 大笨钟V 的家伙 每天敲钟催促码农们爱惜身体早点睡觉 为了增加敲钟的趣味性 还会糟改几句古诗词 其糟改的方法为 去网上搜寻压 ong 韵的古诗词 把句尾的三个字换成 敲笨钟 例如唐代诗人李贺有名句曰 寻章摘句老雕虫 晓月当帘
  • 测试开源C#人脸识别模块ViewFaceCore(2:人脸关键点定位器和活体检测)

    ViewFaceCore模块中的FaceLandmarker类支持识别人脸关键点 也即人脸上的关键位置的坐标 其中主要调用Mark函数返回图片中指定人脸的关键点位置集合 该类需配合FaceDetector类共同使用 FaceLandmark
  • UnityWebRequest下载图片和视频进行使用

    利用空余时间写一下网络下载资源使用 进行熟悉一些UnityWebRequest unity已经抛弃了WWW 这里很简单只需要把脚本挂载就行 所有的界面操作都通过代码实现 资源的下载 删除都做了相应的操作 using System Colle
  • 未定义标识符 HMAC_CTX_init

    这是因为 这是旧版本的代码 HMAC CTX hctx HMAC CTX init hctx HMAC Init ex hctx mac key sizeof mac key EVP sha1 NULL HMAC Update hctx p
  • 什么是数据中台?

    写在前面的话 不要被技术吓到哦 本文尽量写的白话 致力为从事大数据的运营 咨询规划 需求以及想学习大数据的入门者提供知识分享 导读 本文将阐述 为什么要建设数据中台 什么是数据中台 数据中台具备什么样的能力 采用什么技术来实现 一 为什么要
  • QEventLoop源码

    Copyright C 2015 The Qt Company Ltd Contact http www qt io licensing This file is part of the QtCore module of the Qt To