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…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...
OCR MLLM Evaluation
为什么需要评测体系?——背景与矛盾 能干的事: 看清楚发票、身份证上的字(准确率>90%),速度飞快(眨眼间完成)。干不了的事: 碰到复杂表格(合并单元…...
