[muduo网络库]——muduo库EventLoopThread类(剖析muduo网络库核心部分、设计思想)

article/2024/6/13 22:05:10

接着之前我们[muduo网络库]——muduo库Thread类(剖析muduo网络库核心部分、设计思想),我们接下来继续看muduo库中的EventLoopThread类,它和Thread类息息相关。

EventLoopThread类

封装了eventloop线程也就是IO线程,eventloopthread会启动自己的线程,并在里面运行eventloop::loop()。

重要成员变量

EventLoop *loop_;  //线程内部的eventloop*
bool exiting_;     //线程是否退出
Thread thread_;   //线程
std::mutex mutex_; //互斥锁
std::condition_variable cond_; //条件变量
ThreadInitCallback callback_; //线程初始化回调函数
  • 作用如注释所示

重要成员函数

  • 先来看看构造函数和析构函数
EventLoopThread::EventLoopThread(const ThreadInitCallback &cb ,const std::string &name): loop_(nullptr), exiting_(false), thread_(std::bind(&EventLoopThread::threadFunc,this),name), mutex_(), cond_(), callback_(cb){}
EventLoopThread::~EventLoopThread()
{exiting_ = true;if(loop_ != nullptr){loop_->quit();thread_.join();}
}
  1. 初始化给loop_为空,exiting_为否
  2. 注意thread_线程函数是threadFunc
  3. 析构函数中调用EventLoop::quit()Thread::join()
  4. callback_设置为cb
  • 启动一个Loop
EventLoop* EventLoopThread::startLoop()
{thread_.start(); //启动底层新线程EventLoop *loop =nullptr; {std::unique_lock<std::mutex> lock(mutex_);while(loop_==nullptr){cond_.wait(lock);}loop = loop_;       }return loop;
}void EventLoopThread::threadFunc()
{EventLoop loop;if(callback_){callback_(&loop);}{std::unique_lock<std::mutex> lock(mutex_);loop_ = &loop;cond_.notify_one();}loop.loop(); //EventLoop loop => Poller.pollstd::unique_lock<std::mutex> lock(mutex_);loop_=nullptr;
}
  1. 首先,在startLoop中调用了Thread::start(),而这里的thread_的线程函数是threadFunc,在上一篇剖析Thread类时,我们在Thread::start(),看到了一个线程函数func_(),所以func就是构造函数中&EventLoopThread::threadFunc,this 传入的,所以这里会创建线程调用threadFunc()函数,并且主线程阻塞等待EventLoop对象的创建
  2. 此时有两个线程在运行 一个是调用EventLoopThread::startLoop()的线程,一个是执行EventLoopThread::threadFunc()的线程 IO线程
  3. threadFunc是在单独的新线程里面运行的,创建一个独立的Eventloop,和上面的线程是一一对应的 one loop per thread
  4. 将IO线程定义好的loop传入回调
  5. 创建好loop了唤醒主线程,并把loop_给主线程,主线程返回IO线程创建的EventLoop对象
  6. 注意开始执行 loop.loop();,也就是EventLoop loop => Poller.poll,开始一个循环,知道循环结束eventloop析构,把loop_设为空。
总体来说,EventLoopThread提供了对应eventloop和thread的封装,意为I/O线程类,EventLoopThread可以创建一个IO线程,通过startLoop返回一个IO线程的loop,threadFunc中开启loop循环。

补充一下条件变量condition_variable

头文件 #include <condition_variable>
两种形式
  • condition_variable
  • ​condition_variable_any
    相同点:两者都能与std::mutex一起使用。
    不同点:前者仅限于与 std::mutex 一起工作,而后者可以和任何满足最低标准的互斥量一起工作,从而加上了_any的后缀。condition_variable_any会产生额外的开销。
std::condition_variable::wait()

当条件对象的某个 wait 函数被调用的时候,它使用 std::unique_lock(通过 std::mutex) 来锁住当前线程。通常使用 std::unique_lockstd::mutex 来等待,当前线程会一直被阻塞,直到另外一个线程在相同的 std::condition_variable 对象上调用了 notification 函数来唤醒当前线程,该函数会自动调用 lck.unlock() 释放锁,使得其他被阻塞在锁竞争上的线程得以继续执行。

std::condition_variable::wait_for()

可以指定一个时间段,在当前线程收到通知或者指定的时间 rel_time 超时之前,该线程都会处于阻塞状态。而一旦超时或者收到了其他线程的通知,wait_for 返回,剩下的处理步骤和 wait() 类似。

std::condition_variable::notify_one()

唤醒某个等待(wait)线程。如果当前没有等待线程,则该函数什么也不做,如果同时存在多个等待线程,则唤醒某个线程是不确定的(unspecified)。

std::condition_variable::notify_all()

唤醒所有的等待(wait)线程。如果当前没有等待线程,则该函数什么也不做。

代码地址:https://github.com/Cheeron955/mymuduo/tree/master

好了~ 关于muduo库的EventLoopThread类就剖析到这里,要记住里面涉及到的 one loop per thread ,最后,下一篇我们来剖析和这两类息息相关的EventLoopThreadPool类 ~ 我们下一节见 ~~


http://www.ngui.cc/article/show-2100791.html

相关文章

Kafka-核心架构-分区、副本(含副本选举机制)

Kafka概述 Kafka-核心架构-分区 Kafka的分区是将数据在主题&#xff08;Topic&#xff09;中逻辑上划分成多个片段的机制。 分区使得数据可以被水平扩展&#xff0c;提高了Kafka的可伸缩性和吞吐量&#xff0c;并允许数据在集群中分布和并行处理。 1.Kafka 分区的作用 &a…

力扣72-编辑距离

题目链接 记忆化搜索&#xff1a; 解题关键&#xff1a;每次仅考虑两字符串word1、word2分别从0 - i修改成0-j下标的完全匹配(下标表示&#xff09; 临界条件&#xff1a;当 i 或 j 小于0时&#xff0c;表示该字符串为空&#xff0c;编辑距离确定为 y1 或 x1 int dp[501][501…

第6章 动态响应页面内容

1 什么是动态页面 之前案例虽然收到了表单提交的参数但是收到了404错误,因为确实没有页面与请求URI对应,解决这个办法就可以使用动态页面技术,就是动态生成页面内容。 动态响应页面(Dynamic Response Page)是一种动态生成的Web页面,其内容可以根据用户的请求和其他动态变…

linux ndk编译搭建测试

一、ndk下载 NDK 下载 | Android NDK | Android Developers 二、ndk环境变量配置 ndk解压&#xff1a; unzip android-ndk-r26d-linux.zip 环境变量配置&#xff1a; export NDK_HOME/rd/own/test/android-ndk-r26d/ export PATH$PATH:$NDK_HOME 三、编译测试验证 …

word标题格式批量设置方法

1.直接全选ctrlA 全选后然后统一进行编辑&#xff08;适用于标题是紧挨着的情况&#xff09; 2.直接修改对应几级标题格式&#xff0c;然后应用于自己所需要的标题&#xff08;可能会导致上面修改后但是下面不会自动更改&#xff0c;此时用第三种方法&#xff09; 点击[开始…

互联网洗护工厂系统能带来哪方面的便捷

我们的干洗店洗衣洗鞋小程序&#xff0c;为您带来便捷、智能的洗衣洗鞋体验。只需轻触屏幕&#xff0c;即可在线预约洗衣服务&#xff0c;随时随地&#xff0c;无需等待&#xff0c;告别繁琐的电话预约。 用户成为会员&#xff0c;您将独享专属优惠与折扣&#xff0c;更有积分累…

如何配置Always On 可用性组

配置SQL Server的Always On可用性组是一个相对复杂的过程,涉及多个步骤。以下是一个简化的配置流程: 先决条件: 确保你正在使用SQL Server的企业版或开发人员版,因为Always On可用性组功能在这两个版本中是可用的。部署Always On可用性组需要一个Windows Server故障转移群集…

Python内置函数oct()详解

Python中的oct()函数是一个内置函数&#xff0c;用于将一个整数转换成它的八进制字符串表示。 函数定义 oct()函数的基本语法如下&#xff1a; oct(x)x&#xff1a;一个整数。 函数返回x的八进制表示&#xff0c;以字符串形式。 基本用法 将整数转换为八进制 number 64…

vue3 使用WebAssembly 实战

在Vue 3中使用WebAssembly&#xff08;WASM&#xff09;的一个基本示例包括以下几个步骤&#xff1a; 1. 准备WebAssembly模块 首先&#xff0c;你需要一个WebAssembly模块。假设你已经有了一个编译好的.wasm文件&#xff0c;比如名为example.wasm。 2. 加载WebAssembly模块…

几个人脸库对于面部动作识别的功能比较

经粗略研究,insightface只能识别面部特征点的位置,根据这些位置不能直接推出一个人是否在睡觉。 OpenFace 是一个高级的面部行为分析工具,它能够识别和分析多种面部动作单位(Facial Action Coding System, FACS),这些动作单位是根据面部肌肉活动定义的。每个动作单位(A…