仿Muduo库实现高并发服务器——EventLoop模块

        我刚开始看这个模块时,也是看不明白,什么是事件管理模块。

        此时此刻,大领导的背影,还是那么清晰。结合故事模块,慢慢理。

EventLoop模块 成员:

        绿色:

        利用智能指针对new出来的对象进行管理,这里就应该这样做,否则会内存泄露。

 

        蓝色:

        就是事件监控模块,一个EventLoop对象对应一个Poller对象,Poller负责文件描述符的监控,可能有许多客户端的文件描述符,定时管理文件描述符,事件管理文件描述符。在没其他文件描述符。 

        灰色:

        就是定时任务模块,Connection模块调用 EventLoop模块共有接口,将定时任务插入到TimerWheel模块中。在这个项目中,定时器模块只是对客户发起的连接进行了管理(非活跃连接销毁功能)。

        红色:

        就是EventLoop绑定的线程,线程函数是Start()死循环。

 

        绿色:就是EventLoop模块对任务池所做的通知机制,向任务池中插入任务时,会向事件管理文件描述符中写入一个1。

        如果短时间内,有许多任务,但是事件管理文件描述符来不及读取,就会不断对之前那个数字加1,每插入一次就加一。但是将数字读取之后,并没有像TimerWheel模块中的,定时管理文件描述符那样,用读取到的数字去执行定时任务。而是这样做。

        Poller模块 对文件描述符进行事件监控,他是阻塞是等待,有事件就绪,处理就绪事件,哪怕只有一个事件。

        这里有两种情况:一,其他文件描述符有就绪事件,但是任务池中也有事件,首先,将其他文件描述符中就绪事件处理完,在处理任务池中的事件。 

        二,其他文件描述符中没有就绪事件,但是任务池中有事件,这时候 事件管理文件描述符就产生作用,他将Poller从,1,阻塞模式中唤醒,2去执行事件管理文件描述符上的事件

3,再执行任务池中的任务。

任务池是如何运行的

 

        首先创建一个新的任务池对象,将旧的任务池中的任务放到新的任务池中。这样做,不仅没有将下一次到来的任务 和这次要执行的任务搞混,还达到了运行任务的目的。 

线程安全问题:

        首先,线程安全就是只线程会修改进程中的一些资源,如果其他线程用到这个资源,就会产生,错误。因为这个资源被修改了。

        你想,主线程 将建立好的连接给子线程。这句话中就有两对象:主线程,子线程。

        所以我当时就没理解,为什么会有两个线程,由于没有掌握GDB调试,我就硬看和猜测。

我也询问别人,别人提醒了一句,我才恍然大悟。下面就是我用打印呈现出来的现象。

 

         结果发现,客户端刚已连接,服务端就但因这句话,并且出现两个线程id。这就真是了我的猜想。你如果不理解,可以去打印。

        剩下的函数有关模块的讲过,这个模块单拿出来将,也就是大白话,没什么讲的。

EventLoop整体代码:

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 EVENTFD FAILED!!");abort();//让程序异常退出}return efd;}void ReadEventfd() {uint64_t res = 0;int ret = read(_event_fd, &res, sizeof(res));if (ret < 0) {//EINTR -- 被信号打断;   EAGAIN -- 表示无数据可读if (errno == EINTR || errno == EAGAIN) {return;}ERR_LOG("READ EVENTFD FAILED!");abort();}return ;}void WeakUpEventFd() {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 Start() {while(1) {//1. 事件监控, std::vector<Channel *> actives;_poller.Poll(&actives);//2. 事件处理。 for (auto &channel : actives) {channel->HandleEvent();}//3. 执行任务RunAllTask();}}//用于判断当前线程是否是EventLoop对应的线程;bool IsInLoop() {return (_thread_id == std::this_thread::get_id());}void AssertInLoop() {assert(_thread_id == std::this_thread::get_id());}//判断将要执行的任务是否处于当前线程中,如果是则执行,不是则压入队列。void RunInLoop(const Functor &cb) {if (IsInLoop()) {return cb();}return QueueInLoop(cb);}//将操作压入任务池void QueueInLoop(const Functor &cb) {{std::unique_lock<std::mutex> _lock(_mutex);_tasks.push_back(cb);}//唤醒有可能因为没有事件就绪,而导致的epoll阻塞;//其实就是给eventfd写入一个数据,eventfd就会触发可读事件WeakUpEventFd();}//添加/修改描述符的事件监控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); }
};

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

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

相关文章

武汉流星汇聚:亚马逊赋能中小企业,跨境电商市场举足轻重地位稳

在全球经济一体化的浪潮中&#xff0c;跨境电商作为推动国际贸易的重要力量&#xff0c;正以前所未有的速度发展。在这场全球性的商业竞赛中&#xff0c;亚马逊以其卓越的市场表现、强大的技术实力和深厚的品牌影响力&#xff0c;稳居跨境电商市场的领头羊地位&#xff0c;其举…

多任务下载工具.exe

关键代码 void DownloadTask::StartDownload(const QUrl url,QFile *file,qint64 startPoint/* 0 */,qint64 endPoint/* -1 */) {if( NULL file )return;m_HaveDoneBytes 0;m_StartPoint startPoint;m_EndPoint endPoint;m_File file;//根据HTTP协议&#xff0c;写入RANGE…

Vue3基础2

1.Hooks 就是进行数据的封装&#xff0c;同一种类型的 数据 方法 计算属性 &#xff0c;放在一起 命名规范 use功能名称.ts 或.js 创建一个文件夹 hooks 1.useDog.ts import { reactive,onMounted } from "vue"; import axios from "axios";export def…

[数据集][目标检测]红外场景下车辆和行人检测数据集VOC+YOLO格式19069张4类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;19069 标注数量(xml文件个数)&#xff1a;19069 标注数量(txt文件个数)&#xff1a;19069 标…

SQL AI 工具:颠覆数据库管理与分析的创新力量

一、SQL AI 工具的兴起与发展 在当今数字化的时代&#xff0c;数据量呈现爆炸式增长&#xff0c;企业和个人对于高效管理和分析数据的需求日益迫切。传统的数据库管理和查询方式&#xff0c;对于非技术人员来说存在较高的门槛&#xff0c;操作复杂且耗时。这一背景为 SQL AI 工…

人工智能开发NPU使用

1. NPU使用 RK3588 内置 NPU 模块, 处理性能最高可达6TOPS&#xff08;即每秒处理6万亿次操作&#xff09;。这款NPU不仅拥有强大的计算能力&#xff0c;支持TensorFlow、Caffe、Tflite、Pytorch、Onnx NN、Android NN 等常见框架。使用该NPU需要下载RKNN SDK&#xff0c;RKNN…

深度学习--自监督学习

自监督学习是一种无需大量人工标注的数据驱动方法&#xff0c;在生成模型中应用广泛。自监督学习通过利用数据中的固有结构或属性创建“伪标签”&#xff0c;使模型在没有人工标签的情况下进行学习。这种方法既提高了模型的训练效率&#xff0c;又降低了对标注数据的依赖。 概…

VMware安装Ubuntu20.04

1. 下载 整理的镜像链接 阿里网盘&#xff1a; 阿里云盘分享 提取码: l7y1 2. 新建虚拟机向导 选择自定义&#xff0c;然后下一步。 默认配置&#xff0c;下一步。 选择稍后安装操作系统&#xff0c;下一步。 选择操作系统Linux&#xff0c;版本Ubuntu64位&#xff0c;下一…

OCC笔记:Windows下OCC的编译

一、源码下载 进OCC官网下载https://dev.opencascade.org/release即可&#xff0c;或直接Clone它的Git库https://dev.opencascade.org/resources/git_repository&#xff0c;本文用的源码库版本为7.4.0&#xff08;我本机安装的VS2013&#xff0c;我又想用到AIS_ViewCube&…

AList嵌入动态验证码实现动态校验

前言 晓杰利用ALists创建了个网盘资源站&#xff0c;想着如何增加个动态验证码进行验证后才能进行访问下载&#xff0c;刚开始利用了固定的验证码&#xff0c;用户可以通过JS代码中进行绕过或直接拿到验证码&#xff0c;经过晓杰多次优化&#xff0c;最终版本支持动态获取验证…

Linux(面试篇)

目录 什么是Linux 什么是Linux内核&#xff1f; Linux的基本组件是什么&#xff1f; Bash和Dos之间基本区别是什么&#xff1f; 什么是Root账户 什么是Bash? 什么时CLI? Linux的目录结构时怎样的&#xff1f; 什么是硬链接和软链接&#xff1f; 什么叫CC攻击&#…

IP代理可以做爬虫吗?探讨其可行性与相应实践

IP代理在网络爬虫中的应用 在网络爬虫的世界里&#xff0c;IP代理就像是爬虫的“隐形斗篷”&#xff0c;帮助它们在获取数据的过程中隐藏真实身份&#xff0c;避免被目标网站识别和封禁。那么&#xff0c;IP代理到底能否用于爬虫呢&#xff1f;答案是肯定的&#xff01;接下来…

Ajax-04

一.同步代码和异步代码 同步代码&#xff1a;浏览器按照我们书写代码的顺序一行一行地执行程序的。在上一行完成后会执行下一行。 同步代码&#xff1a;逐行执行&#xff0c;需原地等待结果&#xff0c;才继续向下执行 异步代码&#xff1a;可以在执行一个可能长期运行的任务…

docker容器图形化管理之Portainer

docker容器轻量级图形页面管理之Portainer 1、查看portainer镜像 [rootlocalhost ~]# docker search portainer 2、下载portainer镜像 [rootlocalhost ~]# docker pull portainer/portainer #选择喜欢的portainer风格镜像下载 3、启动dockerui容器 [rootlocalhost ~]# doc…

昂科烧录器支持Melexis迈来芯的位置传感器MLX90365KDC

芯片烧录行业领导者-昂科技术近日发布最新的烧录软件更新及新增支持的芯片型号列表&#xff0c;其中Melexis迈来芯的位置传感器MLX90365KDC已经被昂科的通用烧录平台AP8000所支持。 MLX90365KDC是第II代Triaxis位置传感器IC。 这款单片器件可凭借其表面的集磁点(IMC)&#xf…

深度全面讲解fs.readFileSync:Node.js中的同步文件读取

在Node.js中&#xff0c;fs模块是用于与文件系统交互的核心模块之一。它提供了一系列的方法用于文件的读取、写入、删除等操作。其中&#xff0c;fs.readFileSync是一个常用的同步方法&#xff0c;用于读取文件的内容。本文将深度全面讲解fs.readFileSync的使用&#xff0c;包括…

游戏服务器架构:基于匿名函数的高性能异步定时器系统

作者&#xff1a;码客&#xff08;ygluu 卢益贵&#xff09; 关键词&#xff1a;游戏服务器架构、匿名函数、高性能、异步定时器。 一、前言 本文主要介绍适用于MMO/RPG游戏服务端的、基于匿名函数做定时器回调函数的、高性能异步触发的定时器系统的设计方案&#xff0c;以解决…

无线液位监测技术在智能化时代的应用新趋势

在工业化进程日益加速的今天&#xff0c;对各类液体存储设施的有效监测与管理成为了保障生产安全、提高运营效率的关键环节。传统液位监测方式往往依赖于有线传感器&#xff0c;不仅安装维护复杂&#xff0c;而且受限于布线距离和环境条件&#xff0c;难以在复杂多变的工业场景…

minio 大视频观看,下载

在线观看 /*** 下载视频文件 fileName文件路径名称 文件路径 BacketName/video/1111.mp4 需要截取桶名后面的路径 video/1111.mp4 video前面不要带/ ** param fileName* param request* param response*/public void play(String fileName, HttpServletRequest request,…

Lianwei 安全周报|2024.08.26

新的一周又开始了&#xff0c;以下是本周「Lianwei周报」&#xff0c;我们总结推荐了本周的政策/标准/指南最新动态、热点资讯和安全事件&#xff0c;保证大家不错过本周的每一个重点&#xff01; 政策/标准/指南最新动态 01 关于印发《全国重点城市IPv6流量提升专项行动工作方…