当前位置: 首页 > news >正文

仿muduo库实现高并发服务器---线程池模块Eventloop的实现

目录

一、前置知识

eventfd的介绍

EventLoop的整体介绍

Eventloop处理模块流程

总结

二、成员变量

三、成员函数


一、前置知识

eventfd的介绍

eventfd:创建一个描述符用于实现时间通知本质是在内核里面管理的计数器,创建eventfd就会在内核中写入一个数字---用于表示事件通知次数,可以使用read进行数据的读取,读取到的数据就是通知次数

假设每次给eventfd中写入1,就表示通知一次,连续写了三次之后,read读数字就是3,读取之后计数清零

用处:Eventloop中实现消息通知机制

函数:

int eventfd(unsigned int initval, int flags)

参数:

initval:计数初值

flag:EFD_CLOEXEC 禁止进程复制

EFD_NONBLOCK 启动非阻塞属性

返回值:返回一个文件描述符用于操作

eventfd也是通过read write close进行操作

read/write进行IO的时候只能是一个8字节数据

EventLoop的整体介绍

Eventloop:进行事件监控,以及事件处理的模块

关键点: 这个模块是和线程一一对应的,监控了一个链接,而这个链接一旦就绪,就要进行数据处理,就会存在线程安全,因此我们需要将一个链接的事件监控,以及链接事件处理等其他动作放在同一个线程中进行

如何保证一个链接的所有操作都在eventloop对应的线程中进行

给eventloop模块中,添加一个任务队列,对所有操作都进行一次封装,将链接的操作当作任务添加到任务队列中

Eventloop处理模块流程

1、在线程中对于描述符进行监控

2、有描述符就绪,则对描述符进行事件处理保证处理回调函数的操作都在同一个流程中

3、所有的就绪事件处理完了,在将队列中的任务一一执行

总结

1、事件监控

使用Poller模块(有事件就绪则进行事件处理)

2、执行任务队列中的任务

一个线程安全的队伍

注意:有可能因为等待IO描述符事件就绪,导致执行流流程阻塞,这时候任务队列的任务得不到执行因此得有一个事件通知东西,唤醒阻塞

二、成员变量

1、线程id _thread_id

2、唤醒IO事件监控导致的阻塞 _event_fd

3、创建一个_event_fd的事件描述 std::unique_ptr<Channel> _event_channel;

4、进行所有描述付的事件监控 Poller _poller;

5、任务池 std::vector<Functor> _tasks;

6、实现线程安全 std::mutex _mutex;

当事件就绪,需要处理,处理过程中,如果对链接要进行某些操作的时候,这些操作必须在Eventloop线程中执行的,保证对链接各项操作都是线程安全的

(1)本身就在线程中(立即执行)

(2)不在 (需要加入任务池中)

using Functor = std::function<void()>; std::thread::id _thread_id; int _event_fd; Poller _poller; std::unique_ptr<Channel> _event_channel; std::vector<Functor> _task; std::mutex _mutex;

三、成员函数

1、执行线程池中所有的任务

void RunAllTask() { std::vector<Functor> functor; { std::unique_lock<std::mutex> _lock(_mutex); _task.swap(functor); } for (auto &f : functor) { f(); } return; }

2、创建eventfd

static int CreatEventFd() { int efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); if (efd < 0) { ERR_LOG("EVENTFD FAILED"); abort(); } return efd; }

3、读取eventfd

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 FAILED"); abort(); } return; }

4、初始化Eventloop

这里Channel内部有Eventloop的执政完成监控的更新

5、Start

三步走

事件监控

就绪事件处理

执行任务

void Start() { while (1) { std::vector<Channel *> active; _poller.Poll(&active); for (auto &channel : active) { channel->HandleEvents(); } RunAllTask(); } }

6、判断当前线程是否是EventLoop对应的线程

bool IsInloop() { return (_thread_id == std::this_thread::get_id()); }

void AssertInloop() { assert(_thread_id == std::this_thread::get_id()); }

7、判断将要执行的任务是否处于当前线程中,如果是则执行,如果不是则压入队列

void RunInLoop(const Functor &cd) { if (IsInloop() == true) { return cd(); } return QueueInLoop(cd); }

8、将操作压入任务池

void QueueInLoop(const Functor &cd) { { std::unique_lock<std::mutex> _lock(_mutex); _task.push_back(cd); } WeakUpEventFd(); }

9、唤醒线程

就是向线程中写入一个event_fd;

9、添加/修改描述符的事件监控

void UpdateEvent(Channel *channel) { return _poller.UpdateEvent(channel); }

10、移除描述符的事件监控

void RemoveEvent(Channel *channel) { return _poller.RemoveEvent(channel); }
http://www.jsqmd.com/news/470523/

相关文章:

  • CCP基本命令—选择标定数据页、获取DAQ列表大小
  • 导入Rsoft接口库
  • 网络通信与 TCP/IP 五层协议模型详解
  • 2026年质量好的异性拉伸件公司推荐:五金拉伸件生产厂家推荐几家 - 行业平台推荐
  • No.103.基于博途的PLC三种模式通行时间可调的复杂路口交通灯程序设计与仿真,带登录系统登...
  • 2026年比较好的食品生产线公司推荐:麦片生产线/糖果生产线/复合薯片生产线值得信赖的生产厂家 - 行业平台推荐
  • java基于springboot的毕业生招聘职位推荐系统设计
  • java关键字之final学习
  • 基于Vue.js的电商前端模板:Vue-Dashboard-Template的设计与实现
  • 2026年比较好的包装机公司推荐:给袋包装机/巧克力包装机/糖果枕式包装机工厂直供哪家专业 - 行业平台推荐
  • Windows应用程序漏洞及防御
  • 2025 1-12
  • 线缆中的正向、反向、同向、异向的具体意思是什么?
  • 低温传感器质量检测的具体步骤
  • 从2026消费趋势洞察看春节礼品推荐方向,附选购清单 - yangyuan-shunfeng
  • Day2-MySQL-SQL-1
  • 2026年重庆特色美食评测:这几家口碑老店值得专程前往,特色美食/火锅店/社区火锅/火锅/美食,特色美食品牌推荐 - 品牌推荐师
  • 校园跑腿服务平台的技术实现与案例分析
  • 为什么要深入学习JVM底层原理
  • 快看2026年2月国内热门智适应动力模块工厂推荐排行,回风箱式电子除尘净化器/空调机组,智适应动力模块供应厂家选哪家 - 品牌推荐师
  • Whatever
  • 2026年国产CRM排行榜深度解析:十款本土客户管理系统终极指南 - 纷享销客智能型CRM
  • 盘点加油卡回收的4个关键步骤,轻松解决常见问题 - 团团收购物卡回收
  • 有人已经用小龙虾OpenClaw偷钱和数据了!
  • 2026年进口岩板品牌服务商家怎么收费,价格大揭秘 - 工业品牌热点
  • ClaudeCode安装并配置第三方模型
  • HN2302GN_20V4A 封装SOT23 MOSFET场效应管详细分析(核心应用场景与电路)
  • 3关键字B+树构建详解
  • 2026年中小企业主必看:北京代理记账公司选型指南与精准适配建议 - 十大品牌推荐
  • Vibe Coding氛围编程