1.8.C++项目:仿muduo库实现并发服务器之eventloop模块的设计
项目完整在:
文章目录
- 一、eventloop模块:进行事件监控,以及事件处理的模块
- 二、提供的功能
- 三、实现思想
- (一)功能
- (二)意义
- (三)功能设计
- 四、框架
- 五、代码
一、eventloop模块:进行事件监控,以及事件处理的模块
- 进行事件监控管理的模块
- 这个模块就是我们所说的One thread one loop 中的loop,也就是我们所说的Reactor
- 这个模块必定是一个模块对于一个线程
二、提供的功能
这个模块和线程是一一对应的!
监听了一个链接,如果这个连接一旦就绪,就要进行事件处理!
但是如果这个描述符,在多个线程中都触发了了事件,进行处理,就会存在线程安全问题!
因此我们需要将一个链接的事件监控, 以及连接事件处理,以及其他操作都放在同一个线程中!
如何保证一个连接的所有操作都在eventloop对应的线程中!
给eventLOOP模块中,都添加一个任务队列!
对连接的所有操作,都进行一次封装,将对连接的操作当作任务都添加到任务队列中!
三、实现思想
(一)功能
- 在线程中对描述符进行事件监控!
- 有描述符就绪则对描述符进行事件处理,(如何保证处理回调函数中的操作都在线程中)
- 所有的就绪事件处理完了,这时候再去将任务队列中的所有任务一一执行! 这样能够保证对于所有链接的所有操作,都是在一个线程中进行的,不涉及线程安全问题!
但是对于任务队列中的操作有线程安全的问题,只需要给task的操作架一把锁即可!
(二)意义
对于服务器的所有事件都是由EventLoop模块来完成
每一个Connection连接,都会绑定一个EventLoop模块和线程,因为外界对于连接的所有操作,都要放到同一个线程中进行!
(三)功能设计
- 事件监控
使用Poller模块
有事件就绪则进行事件处理! - 执行任务队列中的任务!
注意点:
因为有可能因为等待描述符IO事件就绪,执行流流程阻塞,这个时候任务对立中的任务得不到执行!
因此得有一个事件通知的东西,能够唤醒事件监控的阻塞!
当事件就绪,需要处理的时候,处理过程中,如果对连接要进行某些操作!
这些操作必须要在Eventloop对应的线程中进行,保证对连接的各项操作都是线程安全的。 - 如果执行的操作就在本线程中,不需要将操作压入队列了,可以直接执行!
- 如果执行的操作不在线程中,才需要加入任务池,等到事件处理完了之后就行执行任务!
四、框架
class Eventloop {
private:std::thread::id _thread_id; // 线程IDint _event_fd // eventfd 唤醒IO事件监控有可能的阻塞!!!Poller _poller; // 进行所有描述符的事件监控using Functor = std::function<void()>;std::vector<Functor> _task; // 任务池std::mutex _mutex; // 实现任务池操作的线程安全!!!
public:void runAllTask();
public:Eventloop();void runInLoop(const Functor&cb); // 判断将要执行的任务是否处于当前线程中,如果是则执行,不是则压入队列。void queueInLoop(const Functor&cb); // 将操作压入任务池!bool isInLoop(); //永远判断当前线程是否是EventLoop所对应的线程void updateEvent(Channel* channel); // 添加/修改描述符的事件监控void removeEvent(Channel* channel); // 移除描述符的监控void Start(); // 任务监控完毕进行处理任务! 三步走:事件监控-》就绪事件处理-》执行任务};
五、代码
class EventLoop {
private:using Functor = std::function<void()>;std::thread::id _thread_id; // 线程IDint _event_fd; // eventfd 唤醒IO事件监控有可能的阻塞!!!std::unique_ptr<Channel> _event_channel; Poller _poller;//进行所有描述符的事件监控std::vector<Functor> _tasks; // 任务池std::mutex _mutex; // 实现任务池操作的线程安全!!!TimerWheel _timer_wheel;//定时器模块
public: // 执行任务池中的所有任务!!void runAllTask() {std::vector<Functor> functor; {std::unique_lock<std::mutex> _lock(_mutex); // 出了作用域,锁就会被解开!!_tasks.swap(functor);}for (auto &f : functor) {f();}return ;}static int createEventFd() {int efd = eventfd(0,EFD_CLOEXEC | EFD_NONBLOCK);if (efd < 0) {ERR_LOG("CREATE ENVENTED FAILED !!!");abort();}return efd;}void readEventfd() {uint64_t res = 0;int ret = read(_event_fd,&res,sizeof(res));if (ret < 0) {if (errno == EINTR || errno == EAGAIN) {return;}ERR_LOG("READ EVENTFD FAILED!");abort();}return ;}void weakEventFd() {uint64_t val = 1;int ret = write(_event_fd,&val,sizeof(val));if (ret < 0) {if (errno == EINTR) {return;}ERR_LOG("READ EVENTFD FAILED!");abort();}return ;}
public:EventLoop():_thread_id(std::this_thread::get_id()), _event_fd(createEventFd()), _event_channel(new Channel(this, _event_fd)),_timer_wheel(this) {//给eventfd添加可读事件回调函数,读取eventfd事件通知次数_event_channel->setReadCallback(std::bind(&EventLoop::readEventfd, this));//启动eventfd的读事件监控_event_channel->enableRead();}void runInLoop(const Functor&cb) { // 判断将要执行的任务是否处于当前线程中,如果是则执行,不是则压入队列。if (isInLoop()) {return cb();}}void queueInLoop(const Functor&cb) { // 将操作压入任务池!std::unique_lock<std::mutex> _lock(_mutex);//唤醒有可能因为没有事件就绪,而导致的epoll阻塞;//其实就是给eventfd写入一个数据,eventfd就会触发可读事件_tasks.push_back(cb);weakEventFd();}bool isInLoop() { //永远判断当前线程是否是EventLoop所对应的线程return (_thread_id == std::this_thread::get_id());}void updateEvent(Channel* channel) {// 添加/修改描述符的事件监控return _poller.UpdateEvent(channel); }void removeEvent(Channel* channel) { // 移除描述符的监控return _poller.removeEvent(channel);}void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &cb) { return _timer_wheel.TimerAdd(id, delay, cb); }void TimerRefresh(uint64_t id) { return _timer_wheel.TimerRefresh(id); }void TimerCancel(uint64_t id) { return _timer_wheel.TimerCancel(id); }bool HasTimer(uint64_t id) { return _timer_wheel.HasTimer(id); }void Start() { // 任务监控完毕进行处理任务! // 三步走:事件监控-》就绪事件处理-》执行任务std::vector<Channel*> actives;_poller.Poll(&actives);for (auto &channel : actives) {channel -> handleEvent();}runAllTask();}};
相关文章:

1.8.C++项目:仿muduo库实现并发服务器之eventloop模块的设计
项目完整在: 文章目录 一、eventloop模块:进行事件监控,以及事件处理的模块二、提供的功能三、实现思想(一)功能(二)意义(三)功能设计 四、框架五、代码 一、eventloop模…...

Linux基本指令(二)
💓博主个人主页:不是笨小孩👀 ⏩专栏分类:数据结构与算法👀 C👀 刷题专栏👀 C语言👀 🚚代码仓库:笨小孩的代码库👀 ⏩社区:不是笨小孩👀 🌹欢迎大…...
量化交易全流程(五)
本节目录 策略回测 多因子模型 本节主要讨论回测相关的内容,包括两种不同的回测机制,即向量化回测和事件驱动回测;如何灵活使用开源工具来编写自己的回测程序;不同实现方式的优劣对比等。 在我们研究策略的时候,需要…...
聊聊MySQL的InnoDB引擎与MVCC
目录 一、InnoDB引擎 1.1逻辑存储结构 1). 表空间 2). 段 3). 区 4). 页 5). 行 1.2架构 1.2.1内存结构 1). Buffer Pool 2). Change Buffer 3). Adaptive Hash Index 4). Log Buffer 1.2.2磁盘结构 1). System Tablespace 2). File-Per-Table Tablespaces 3). …...

小病变检测:Gravity Network for end-to-end small lesion detection
论文作者:Ciro Russo,Alessandro Bria,Claudio Marrocco 作者单位:University of Cassino and L.M. 论文链接:http://arxiv.org/abs/2309.12876v1 内容简介: 1)方向:医学影像中小病变检测 2࿰…...

Flink--7、窗口(窗口的概念、分类、API、分配器、窗口函数)、触发器、移除器
星光下的赶路人star的个人主页 内心的平静始于不再让他人掌控你的感情 文章目录 0、前言1、窗口(Window)1.1 窗口的概念1.2 窗口的分类1.3 窗口API概览1.4 窗口分配器(Window Assigner)1.4.1 时间窗口1.4.2 计数窗口 1.5 窗口函数…...

vscode 注释插件koroFileHeader
https://blog.51cto.com/u_15785499/5664323 https://blog.csdn.net/weixin_67697081/article/details/129004675...

Centos7安装php-fpm
目录 第一步:查看系统IP地址和网卡名称 第二步:更改网络配置模式 第三步、重启network 查看iptablies ,将第十行,十一行删除 第四步:关闭config 第五步:创建nginx 文件夹 查看目录下的文件 进入nginx文件夹 第…...

计算机网络(五):运输层
参考引用 计算机网络微课堂-湖科大教书匠计算机网络(第7版)-谢希仁 1. 运输层概述 之前所介绍的计算机网络体系结构中的物理层、数据链路层以及网络层它们共同解决了将主机通过异构网络互联起来所面临的问题,实现了主机到主机的通信ÿ…...

适合在校学生的云服务器有哪些?
随着云计算技术的发展,越来越多的学生开始使用云服务器来进行学习和实践。对于学生来说,选择一款便宜的云服务器不仅可以帮助他们降低成本,还可以提高学习和实践的效率。本文将介绍几款适合学生使用的便宜云服务器。 1、腾讯云学生服务器【点…...

计算机竞赛 深度学习驾驶行为状态检测系统(疲劳 抽烟 喝水 玩手机) - opencv python
文章目录 1 前言1 课题背景2 相关技术2.1 Dlib人脸识别库2.2 疲劳检测算法2.3 YOLOV5算法 3 效果展示3.1 眨眼3.2 打哈欠3.3 使用手机检测3.4 抽烟检测3.5 喝水检测 4 最后 1 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 基于深度学习的驾…...

想要精通算法和SQL的成长之路 - 验证二叉搜索树和不同的二叉搜索树
想要精通算法和SQL的成长之路 - 验证二叉搜索树和不同的二叉搜索树 前言一. 验证二叉搜索树二. 不同的二叉搜索树三. 不同的二叉搜索树II 前言 想要精通算法和SQL的成长之路 - 系列导航 二叉搜索树的定义: 节点的左子树只包含 小于 当前节点的数。节点的右子树只包…...

SpringCloudAlibaba 相关组件的学习一
目录 前言 系统架构演变 1、单体架构 2、垂直架构 3、分布式架构 4、SOA架构 5、微服务架构 一、微服务架构的介绍 1、微服务架构的常见问题 2 微服务架构的常见概念 2.1 服务治理 2.2 服务调用 2.3 服务网关 2.4 服务容错 2.5 链路追踪 3、微服务架构的常用解决…...
【C语言 模拟实现strncpy函数、strncat函数、strncmp函数、strstr函数】
C语言程序设计笔记---026 C语言之模拟实现strncpy函数、strncat函数、strncmp函数、strstr函数1、介绍strncpy函数1.1、模拟实现strncpy函数 2、介绍strncat函数2.1、模拟实现strncat函数 3、介绍strncmp函数3.1、模拟实现strncmp函数 4、介绍strstr函数4.1、模拟实现strstr函数…...

Mongodb7启动报错排除解决方案
一: 报错信息: [rootwww log]# journalctl -xe -- Unit mongodb.service has begun starting up. /usr/local/mongodb/mongdb7/bin/mongod --help for more information 10月 03 13:47:39 www.yhchange.com systemd[1]: mongodb.service: control process exited, …...

王杰国庆作业day5
...

QT、C++实现地图导航系统(mapSystem)
文章目录 地图导航系统项目应用背景技术栈选择数据处理算法实现界面实现源码展示成果展示源码下载 (免费) 地图导航系统 项目应用背景 电子地图导航系统的主要目的是为用户提供精确、实时的导航和位置信息,以帮助他们在城市或地区内轻松找到…...

STM32 定时器介绍--通用、高级定时器
目录 高级定时器 1.功能框图 1-时钟源 2-时基单元 3-输入捕获 4-输出比较 2.输入捕获的应用 3.输出比较的应用 4.初始化结构体 1-时基初始化结构体 2-输出比较结构体 3-PWM信号 周期和占空比的计算--以通用定时器为例 4-输入捕获结构体 5-断路和死区初始化结构体…...

淘宝天猫渠道会员购是什么意思?如何开通天猫淘宝渠道会员购有什么用?
淘宝天猫渠道会员购是什么意思? 淘宝天猫渠道会员购与淘宝天猫粉丝福利购意思基本相同,都可以领取淘宝天猫大额内部隐藏优惠券、通过草柴APP开通绑定渠道会员还可以获得购物返利。 草柴APP如何绑定开通淘宝天猫渠道会员? 1、手机下载安装「…...

(Note)机器学习面试题
机器学习 1.两位同事从上海出发前往深圳出差,他们在不同时间出发,搭乘的交通工具也不同,能准确描述两者“上海到深圳”距离差别的是: A.欧式距离 B.余弦距离 C.曼哈顿距离 D.切比雪夫距离 S:D 1. 欧几里得距离 计算公式&#x…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...