重写muduo之Thread、EventLoopThread、EventLoopThreadPool

目录

1、概述

2、Thread

2.1 Thread.h

3、EventLoopThread

3.1 EventLoopThread.h

3.2  EventLoopThread.cc

4、 EventLoopThreadPool

4.1 EventLoopThreadPool.h

4.2 EventLoopThreadPool.cc


1、概述

管理事件循环线程的调度的

打包了一个EventLoop和线程,绑定了一个loop跟thread,让这个loop运行在这个thread上,在这个thread里面创建一个loop(one loop per thread)

底层封装的线程

2、Thread

2.1 Thread.h

#pragma once#include "noncopyable.h"#include <functional>
#include <thread>
#include <memory>
#include <string>
#include <atomic>class Thread:noncopyable
{
public:using ThreadFunc=std::function<void()>;//线程函数的函数类型  绑定器和函数对象,就可以传参 explicit Thread(ThreadFunc,const std::string& name=std::string());//构造函数~Thread();void start();//启动当前线程 void join();//当前线程等待其他线程完了再运行下去 bool started()const {return started_;}pid_t tid()const{return tid_;}const std::string& name()const{return name_;}static int numCreated(){return numCreated_;}
private:void setDefaultName();//给线程设置默认的名称bool started_;//启动当前线程 bool joined_;//当前线程等待其他线程完了再运行下去 std::shared_ptr<std::thread> thread_;//自己来掌控线程对象产生的时机pid_t tid_;ThreadFunc func_;//存储线程函数 std::string name_;//调试的时候打印 static std::atomic_int numCreated_;//对线程数量计数 
};

 我们使用C++结合lambda表达式 的方法来实现,非常方便。

3、EventLoopThread

3.1 EventLoopThread.h

#pragma once#include "noncopyable.h"
#include "Thread.h"#include <functional>
#include <mutex>
#include <condition_variable>
#include <string>class EventLoop;class EventLoopThread:noncopyable
{
public:using ThreadInitCallback=std::function<void(EventLoop*)>;EventLoopThread(const ThreadInitCallback& cb=ThreadInitCallback(), //线程初始化的回调 const std::string& name=std::string());~EventLoopThread();EventLoop* startLoop();//开启循环 
private:void threadFunc();//线程函数,创建loop EventLoop* loop_;bool exiting_;//是否退出循环Thread thread_;std::mutex mutex_;std::condition_variable cond_;ThreadInitCallback callback_;//初始化操作 
};

3.2  EventLoopThread.cc

#include "EventLoopThread.h"
#include "EventLoop.h"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();}
}EventLoop* EventLoopThread::startLoop()//开启循环 
{thread_.start();//启动底层的新线程//启动后执行的是EventLoopThread::threadFuncEventLoop* loop=nullptr;{std::unique_lock<std::mutex> lock(mutex_);while(loop_==nullptr)//loop指针还没有初始化{cond_.wait(lock);挂起,等待}loop=loop_;}return loop;
}//下面这个方法,是在单独的新线程里面运行的
void EventLoopThread::threadFunc()//线程函数,创建loop 
{EventLoop loop;//创建一个独立的eventloop,和上面的线程是一一对应的,one loop per threadif(callback_)//如果有回调{callback_(&loop);//绑定loop做一些事情}{std::unique_lock<std::mutex> lock(mutex_);loop_=&loop;//就是运行在这个线程的loop对象,将这个对象初始化好之后(loop指针指向loop对象),才能唤醒(通知)cond_.notify_one();//唤醒1个线程,被唤醒后去访问loop指针}loop.loop();//EventLoop loop=>Poller.pollstd::unique_lock<std::mutex> lock(mutex_);loop_=nullptr;
}

4、 EventLoopThreadPool

这个很明显,是池的概念。是一个事件线程池,管理eventloop,eventloop绑定的就是一个线程。

用户最开始创建的loop,对应的是一个线程

4.1 EventLoopThreadPool.h

#pragma once
#include "noncopyable.h"#include <functional>
#include <string>
#include <vector>
#include <memory>class EventLoop;
class EventLoopThread;class EventLoopThreadPool:noncopyable
{
public:using ThreadInitCallback=std::function<void(EventLoop*)>;EventLoopThreadPool(EventLoop* baseLoop,const std::string& nameArg);~EventLoopThreadPool();void setThreadNum(int numThreads){numThreads_=numThreads;}void start(const ThreadInitCallback& cb=ThreadInitCallback());//如果工作在多线程中,baseloop_默认以轮询的方式分配channel给subloopEventLoop* getNextLoop();std::vector<EventLoop*> getAllLoops();bool started()const{return started_;}const std::string name() const{return name_;}
private:EventLoop* baseLoop_;//EventLoop loop;std::string name_;bool started_;int numThreads_;int next_;std::vector<std::unique_ptr<EventLoopThread>> threads_;std::vector<EventLoop*> loops_;
};

4.2 EventLoopThreadPool.cc

#include "EventLoopThreadPool.h"
#include "EventLoopThread.h"#include <memory>EventLoopThreadPool::EventLoopThreadPool(EventLoop* baseLoop,const std::string& nameArg):baseLoop_(baseLoop),name_(nameArg),started_(false),numThreads_(0),next_(0){}
EventLoopThreadPool::~EventLoopThreadPool()
{}void EventLoopThreadPool::start(const ThreadInitCallback& cb)
{started_=true;for(int i=0;i<numThreads_;i++){char buf[name_.size()+32];snprintf(buf,sizeof buf,"%s%d",name_.c_str(),i);EventLoopThread* t=new EventLoopThread(cb,buf);threads_.push_back(std::unique_ptr<EventLoopThread>(t));loops_.push_back(t->startLoop());//底层创建线程,绑定一个新的EventLoop,并返回该loop的地址}//整个服务端只有一个线程,运行着baseloopif(numThreads_==0&&cb){cb(baseLoop_);}
}//如果工作在多线程中,baseloop_默认以轮询的方式分配channel给subloop
//通过轮询的方式从子线程中取loop(循环)
//IO线程  baseloop  用作处理用户的连接事件
//工作线程  新创建的loop  用于处理用户的读写事件
EventLoop* EventLoopThreadPool::getNextLoop()
{EventLoop* loop=baseLoop_;if(!loops_.empty())//通过轮询获取下一个处理事件的loop{loop=loops_[next_];next_++;if(next_>=loops_.size()){next_=0;}}return loop;
}std::vector<EventLoop*> EventLoopThreadPool::getAllLoops()
{if(loops_.empty()){return std::vector<EventLoop*>(1,baseLoop_);}else{loops_;}
}

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

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

相关文章

项目经理【过程】原则

系列文章目录 【引论一】项目管理的意义 【引论二】项目管理的逻辑 【环境】概述 【环境】原则 【环境】任务 【环境】绩效 【人】概述 【人】原则 【人】任务 【人】绩效 【过程】概念 【过程】原则 一、质量管理水平、质量管理的发展 1.1 质量管理水平 1.2 质量管理的发展 …

NAS选购全方位解析,性价比才是硬道理 | 2024年618威联通NAS选购攻略

NAS选购全方位解析&#xff0c;性价比才是硬道理 | 2024年618威联通NAS选购攻略 哈喽小伙伴们好&#xff0c;我是Stark-C~&#xff0c;临近618&#xff0c;今天和大家谈谈NAS的选购问题。 关注我的小伙伴都知道&#xff0c;经过我手头折腾的NAS设备非常多&#xff0c;除了群晖…

如果出现一个工具,可以让前端开发彻底不用再手写UI,这个工具意义大吗?干货!

求这样的一个工具&#xff0c;可以让后端开发、嵌入式开发、产品经理、UI设计师都能用&#xff0c;注意&#xff0c;不是在一个简单的静态页生成&#xff0c;也不是类似飞冰那种 generator &#xff0c;而是真正让设计师和开发者在各自的那侧达成自治&#xff0c;可以做到吗&am…

;【排列【

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

C++进阶之路:深入理解编程范式,从面向过程到面向对象(类与对象_上篇)

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

如何使用Tushare+ Backtrader进行股票量化策略回测

数量技术宅团队在CSDN学院推出了量化投资系列课程 欢迎有兴趣系统学习量化投资的同学&#xff0c;点击下方链接报名&#xff1a; 量化投资速成营&#xff08;入门课程&#xff09; Python股票量化投资 Python期货量化投资 Python数字货币量化投资 C语言CTP期货交易系统开…

【代码随想录算法训练营第37期 第二天 | LeetCode977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵II】

代码随想录算法训练营第37期 第二天 | LeetCode977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵II 一、977.有序数组的平方 解题代码C&#xff1a; class Solution { public:vector<int> sortedSquares(vector<int>& nums) {int len nums.size();fo…

ICode国际青少年编程竞赛- Python-2级训练场-列表入门

ICode国际青少年编程竞赛- Python-2级训练场-列表入门 1、 Dev.step(3)2、 Flyer.step(1) Dev.step(-2)3、 Flyer.step(1) Spaceship.step(7)4、 Flyer.step(5) Dev.turnRight() Dev.step(5) Dev.turnLeft() Dev.step(3) Dev.turnLeft() Dev.step(7) Dev.turnLeft() Dev.…

hive中开窗函数row_number的使用

row_number()函数介绍 row_number()开窗函数的一种&#xff0c;和over()函数结合一起使用&#xff0c;可以实现对数据的分组和排序。 使用示例 现在有一张表&#xff0c;数据如下 ----------------------- | Year | Region | Sales | ----------------------- | 2022 | E…

5月8日爬楼梯+使用最小花费爬楼梯

70.爬楼梯 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方法可以爬到楼顶。 1. 1 阶 1 阶 2. 2 阶 示…

EVENT事件调度(应用层级)操作注意事项

文章目录 简要注意事项API说明1、1毫秒计时驱动2、1秒计时驱动2、设置一个单位时间为1毫秒的周期性事件3、设置一个单位时间为1秒的周期性事件4、单次触发事件5、清除停止事件5、缓存事件触发标志6、获取事件状态 示例源码 简要 最大支持32个事件标志管理&#xff0c;倒计时精度…

java Io流学习归纳

- 固定套路&#xff1a;1. 创建IO流对象 2. 读写文件 3. 关闭流 - 固定的API方法&#xff1a; //读&#xff1a;read()&#xff1a; /*读一个字节/字符*/int read() /*读一个字节/字符数组*/ int read(byte[] buf)int read(char[] cbuf) //写&#xff1a;wri…

【数字经济】上市公司供应链数字化数据(2000-2022)

数据来源&#xff1a; 时间跨度&#xff1a;2000-2022年 数据范围&#xff1a;各上市企业 数据指标&#xff1a; 样例数据&#xff1a; 参考文献&#xff1a;[1]刘海建,胡化广,张树山,等.供应链数字化的绿色创新效应[J].财经研究,2023,49(03):4-18. 下载链接&#xff1a;https:…

Linux(openEuler、CentOS8)基于chrony企业内网NTP服务器搭建实验

一、知识点 chrony 是由 守护进程 chronyd 以及 命令行工具 chronyc 组成的 chronyd 在后台静默运行并通过 123 端口与时间服务器定时同步时间&#xff0c;默认的配置文件是 /etc/chrony.conf chronyc 通过 323 端口与 chronyd 交互&#xff0c;可监控 chronyd 的性能并在运…

基于springboot+vue+Mysql的口腔管理平台

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

【3dmax笔记】026:挤出和壳修改器的使用

文章目录 一、修改器二、挤出三、壳 一、修改器 3ds Max中的修改器是一种强大的工具&#xff0c;用于创建和修改复杂的几何形状。这些修改器可以改变对象的形状、大小、方向和位置&#xff0c;以生成所需的效果。以下是一些常见的3ds Max修改器及其功能&#xff1a; 挤出修改…

Day22 代码随想录打卡|字符串篇---实现 strStr()

题目&#xff08;leecode T28&#xff09;&#xff1a; 给你两个字符串 haystack 和 needle &#xff0c;请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 开始&#xff09;。如果 needle 不是 haystack 的一部分&#xff0c;则返回 -1…

第 8 章 电机测速(自学二刷笔记)

重要参考&#xff1a; 课程链接:https://www.bilibili.com/video/BV1Ci4y1L7ZZ 讲义链接:Introduction Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 8.3.3 电机测速01_理论 测速实现是调速实现的前提&#xff0c;本节主要介绍AB相增量式编码器测速原理。 1.概…

可视化面板布局适配屏幕-基于 flexible.js + rem 智能大屏适配

可视化面板布局适配屏幕-基于 flexible.js rem 智能大屏适配 VScode 安装cssrem插件引入flexible.js在之后的开发都使用rem为单位&#xff0c;安装cssrem插件就是为了快捷将px转为rem我们的设计稿是1920px&#xff0c;设置最小宽度为1024px&#xff0c;最后&#xff0c;我们可…

管理非结构化数据

据IDC调查&#xff0c;当前企业80%的数据为非结构化数据或半结构化数据&#xff0c;而结构化数据是他们管理的重点&#xff0c;数据的大头-非结构化数据却被忽视。然而&#xff0c;非结构化数据也有着它的价值。 管理好非结构化数据对于公司释放有价值资产、高效决策和高效部署…