基于多反应堆的高并发服务器【C/C++/Reactor】(中)在EventLoop的任务队列中添加新任务

news2024/11/18 5:53:29

  1. 任务队列是一个链表,每个节点包含channel类型文件描述符操作类型
  2. 在添加节点时,需要考虑线程同步,并确保节点被正确地添加到链表中
  3. 节点的操作可以写到另一个函数中,以便于程序的维护。
  4. 在添加任务节点时,需要加互斥锁,因为有可能是当前线程主线程进行添加操作。

本文主要介绍了在dispatcher中的处理流程,包括线程同步以及节点的添加和操作。其中,任务队列是一个链表,每个节点包含channel类型、文件描述符和操作类型。在添加节点时,需要考虑线程同步,并确保节点被正确地添加到链表中。

  • EventLoop.h
// 添加任务到任务队列
int eventLoopAddTask(struct EventLoop* evLoop,struct Channel* channel,int type);
  • EventLoop.c

(1) 为什么在上面添加链表节点的时候需要加互斥锁

  • 因为有可能是当前线程去添加,也有可能是主线程去添加。

(2) 如果当前的线程是主线程,那么我们能够让主线程进行节点的处理

  • 肯定不能,因为你当前主线程它只能负责和客户端建立连接,如果这个连接建立好了,剩下的事情都是需要由这个子线程来完成的。所以主线程肯定不会给你去处理任务队列里边的节点。在主线程里边,其实它是有一个反应堆模型的,在当前的这个子线程里边也有一个反应堆模型。每个反应堆模型里边都有一个Dispatcher。关于这个Dispatcher就是epoll、poll、或者select模型,所以主线程去处理的话,这个任务就放到主线程的那个Dispatcher里边了,这样很显然是不对的。故在子线程的任务队列里边有了任务之后,还需要交给子线程的Dispatcher去处理。因此这个节点的处理,还需要判断当前线程到底是什么线程。
  • 如果它是主线程不能让它去处理,如果是子线程,直接让它去处理。 
// 添加任务到任务队列
int eventLoopAddTask(struct EventLoop* evLoop,struct Channel* channel,int type) {
    // 加锁,保护共享资源
    pthread_mutex_lock(&evLoop->mutex);
    // 创建新节点,后添加到任务队列中去
    struct ChannelElement* node = (struct ChannelElement*)malloc(sizeof(struct ChannelElement));
    node->channel = channel;
    node->type = type;
    node->next = NULL;
    // 链表为空
    if(evLoop->head == NULL) {
        evLoop->head = evLoop->tail = node;
    }else {
        evLoop->tail->next = node; // 添加
        evLoop->tail = node; // 后移
    }
    pthread_mutex_unlock(&evLoop->mutex);
    // 处理节点
    /**
     * 这个描述假设了一个前提条件,就是当前的EventLoop反应堆属于子线程
     * 细节:
     *  1.对于链表节点的添加:可能是当前线程也可能是其他线程(主线程)
     *      1).修改fd的事件,当前子线程发起,当前子线程处理
     *      2).添加新的fd(意味着和一个新的客户端建立连接,这是由主线程做的,故添加任务节点这个操作肯定是由主线程做的),
     *          添加任务节点的操作是由主线程发起的
     *  2.不能让主线程处理任务队列里边的节点,需要由当前的子线程去处理
    */
    if(evLoop->threadID == pthread_self()) {
        // 当前子线程
        (待续写)...
    }else{
        // 主线程 -- 告诉子线程处理任务队列中的任务
        // 1.子线程在工作 2.子线程被阻塞了:select、poll、epoll
        (待续写)...
    }
    return 0;
}

一、任务队列与文件描述符

  • dispatcher中,存在一个带检测的文件描述符集合。任务队列用于修改这个集合,例如添加、删除或修改。任务队列实际上是一个链表,每个节点代表一个channel元素。每个节点包含三个成员:channel类型、文件描述符和操作类型

二、任务队列的线程同步

  • 由于任务队列可能被多个线程访问,因此在操作任务队列时需要进行线程同步
  • 这意味着在添加新节点到任务队列时,需要确保线程安全

三、节点的添加与操作

  • 节点添加:当链表为空时,直接将新节点设置为任务队列的头;当链表不为空时,将新节点添加到链表的尾部(即tail节点的后边),并更新tail节点的next指针。
  • 节点操作:将节点的处理操作移至另一个函数中,以便于程序的维护

四、线程角色与任务处理

  • 主线程子线程的角色:添加任务节点可能是当前线程或主线程的操作。
  • 主线程负责与新客户端建立连接,而子线程处理其他任务
  • 主线程与子线程的任务分配:主线程不会处理任务队列中的节点,而是通知子线程去处理

五、总结

  • dispatcher中的处理流程,包括任务队列用于修改一个带检测的文件描述符集合、线程同步以及节点的添加和操作。为了确保程序的稳定性和正确性,我们需要关注线程安全和任务分配,确保每个线程都能在其角色范围内高效地工作。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1352189.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

快速打通 Vue 3(三):Vue3 中的 watch 监听器与新特性

很激动进入了 Vue 3 的学习,作为一个已经上线了三年多的框架,很多项目都开始使用 Vue 3 来编写了 这一组文章主要聚焦于 Vue 3 的新技术和新特性 如果想要学习基础的 Vue 语法可以看我专栏中的其他博客 Vue(一):Vue 入…

线程死锁检测组件逻辑与源码

死锁介绍 任务的执行体之间互相持有对方所需的资源而不释放,形成了相互制约而都无法继续执行任务的情况,被称为“死锁”。 死锁案例 线程A持有锁a不释放,需要去获取锁b才能继续执行任务, 线程B持有锁b不释放,需要去…

winform简易用户权限管理系统

一、功能简介 1. 数据库可使用sqlite、mssql、mysql等 2. 管理员账号不管控,其余账号进行权限管控(左侧菜单,表单按钮),且只能看到自己创建的角色、用户 二、操作界面 1. 管理员账号登陆后,左侧菜单栏自动…

【Spark精讲】SparkSQL的RBO与CBO

Spark SQL核心:Catalyst Spark SQL的核心是Catalyst查询编译器,它将用户程序中的SQL/Dataset/DataFrame经过一系列操作,最终转化为Spark系统中执行的RDD。 Catalyst组成部分 Parser :用Antlr将SQL/Dataset/DataFrame转化成一棵未经解析的树…

怎么快速修复mfc140.dll文件?解决mfc140.dll缺失的方法

面对计算机报告的 ​mfc140.dll​ 文件遗失错误,这通常表明系统中缺少一个关键的动态链接库文件,该文件对于运行以 Microsoft Foundation Class (MFC) 库编写的程序十分重要,尤其是那些需要图形界面的应用程序和一些游戏。若没有这个文件&…

清风数学建模-数学规划模型

内容:数学规划模型(cab aeqbeq lbub) 一.题型类型 1.线性规划linprog 2.非线性规划 fmincon 3.整数规划 intlinprog 4.(0-1规划)(特殊的线性整数规划)intlinprog 5.多目标规划 linprog 标…

JumpServer3.0版本(用户管理、邮件、MFA认证配置)

创建用户组 控制台页面可以看见左侧的用户管理下,有用户列表和用户组 点击用户组、点击创建按钮、设置名称,用户不用选择还没建用户,提交即可 创建用户 点击用户列表创建按钮,设置名称、用户名、邮箱等必填项 这个时候用户组选项,可以选好我们创建的用户组了,先创用…

Spring高手之路-Spring Bean、Java Bean和对象的区别与联系

目录 什么是Spring Bean 什么是Java Bean 什么是对象 Spring Bean与Java Bean与对象的联系与区别 联系 区别 什么是Spring Bean 在Spring官方文档中对Bean的解释如下: In Spring, the objects that form the backbone of your application and that are manage…

MySQL数据库高级SQL语句及存储过程

目录 一、高级SQL语句 (一)case语句 1.语法定义 2.示例 (二)空值(NULL) 和 无值( ) 1.区别 2.示例 (1)字符长度 (2)判断方法 ① 空值(NULL) ② 无值( ) (3…

代码随想录算法训练DAY18|二叉树5

算法训练DAY18|二叉树5 513.找树左下角的值 力扣题目链接 给定一个二叉树,在树的最后一行找到最左边的值。 示例 1: 示例 2: 思路 本题要找出树的最后一行的最左边的值。此时大家应该想起用层序遍历是非常简单的了,反而用递归的话会比较难一点。 我…

【通关喜报】腾讯云TDSQL TCP/TCE、云运维tcp 12月认证考试,全员过关,年终冲刺!

2023年12月23日云贝教育有6位学员参加了腾讯云TDSQL-TCP以及TCE认证考试。都取得非常好的成绩~下面我们来看一下各位同学的理论考试和上机考试成绩吧~

BWP频域位置的确定

这里根据协议整理下BWP频域相关参数以及如何确定BWP的频域位置。 BWP的配置包含几个参数 : 1 SCS, CyclePrefix 和locationAndBandwidth。 BWP频域起始位置N_start_BWPOcarrierRBstart,其中Ocarrier 由RRC层参数offsetToCarrier决定。 locationAndB…

Java学习——设计模式——结构型模式2

结构型模式 结构型模式主要涉及如何组合各种对象以便获得更好、更灵活的结构。虽然面向对象的继承机制提供了最基本的子类扩展父类的功能,但结构型模式不仅仅简单地使用继承,而更多地通过组合与运行期的动态组合来实现更灵活的功能。 包括: 1…

Redis命令---String篇 (超全)

目录 1.Redis Setnx 命令 - 只有在 key 不存在时设置 key 的值。简介语法可用版本: > 1.0.0返回值: 设置成功,返回 1 。 设置失败,返回 0 。 示例 2.Redis Getrange 命令 - 返回 key 中字符串值的子字符简介语法可用版本: > 2.4.0返回值: 截取得到…

vue3 接入 Element Plus

vue3 接入 Element Plus vue3 发布已经很久了,官方也已经发布公告,自2023年12月31日起停止对 vue2 版本的维护更新,因此,vue3 正式登上了历史的舞台。组件库一直是前端开发的利器,减少了开发者开发复杂度,提…

计算机毕业设计------基于SpringCloud的实验室管理系统

项目介绍 实验室管理系统的用户可以分为两种:系统管理员和普通用户。系统管理员主要功能: 登录登出、分析数据、管理用户、管理日志、管理实验室、管理预约、维护个人资料、实验室保修管理 用户主要功能: 注册登录、查询实验室、实验室预约…

Edge浏览器的卸载(一分钟版)

一分钟看完不耽误 开整工具下载后 结尾 开整 工具 Remove-MS-Edge 看名字,简单直接 CSDN下载 资源设置是免费的,大家尽管下载 不放心软件安全的话,自己上github地址下载也行 下载后 解压之后 我们打开有gui的,也就是有界面的&…

胡润研究院发布《2023胡润中国最具历史文化底蕴品牌榜》

胡润研究院发布《2023胡润中国最具历史文化底蕴品牌榜》,前十名分别是片仔癀、同仁堂、贵州茅台、五粮液、中国银行、中华、黄山、农业银行、建设银行、汾酒。 榜单调研范围涵盖中国内地具有60年以上历史的为消费者提供产品或服务的品牌,综合考察品牌历史…

polar CTF web upload tutu

一、题目 二、解题 1、上传两个一样的木马提示不是 setu(色图) 2、上传两个图,提示md5值不一样 综上他需要两张md5值相同的图 找工具 fastcoll 可生成两个md5值相同的文件 http://www.win.tue.nl/hashclash/fastcoll_v1.0.0.5.exe.zip 照…

编织Spring魔法:解读核心容器中的Beans机制【beans 一】

欢迎来到我的博客,代码的世界里,每一行都是一个故事 编织Spring魔法:解读核心容器中的Beans机制【beans 一】 前言什么是Spring核心容器Beans的生命周期管理:初始化和销毁方法:各种作用域: beans的配置方式…