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…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...
MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...
使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...
