muduo源码阅读笔记(7、EventLoopThreadPool)
muduo源码阅读笔记(7、EventLoopThreadPool)
Muduo源码笔记系列:
muduo源码阅读笔记(2、对C语言原生的线程安全以及同步的API的封装)
muduo源码阅读笔记(6、EvevntLoop和Thread)
muduo源码阅读笔记(7、EventLoopThreadPool)
前言
与base文件夹下的通用线程池相比,EventLoopThreadPool更加专门化,专为为EventLoopThread而生,专为EventLoop而生,专为One Loop Per Thread而生,专为网络事件驱动而生,专为Muduo而生!
实现
提供的接口:
class EventLoopThreadPool : noncopyable{ public: typedef std::function<void(EventLoop*)> ThreadInitCallback; EventLoopThreadPool(EventLoop* baseLoop, const string& nameArg); ~EventLoopThreadPool(); void setThreadNum(int numThreads) { numThreads_ = numThreads; } void start(const ThreadInitCallback& cb = ThreadInitCallback()); // valid after calling start() /// round-robin EventLoop* getNextLoop(); /// with the same hash code, it will always return the same EventLoop EventLoop* getLoopForHash(size_t hashCode); std::vector<EventLoop*> getAllLoops(); bool started() const { return started_; } const string& name() const { return name_; } private: EventLoop* baseLoop_; // 启动EventLoopThreadPool的EventLoop string name_; // 线程池名 bool started_; // 启动了? int numThreads_; // EventLoopThread线程的数量 int next_; // 使用round-robin算法做线程的负载均衡,调度到了哪一个线程? std::vector<std::unique_ptr<EventLoopThread>> threads_; // 线程池本体 std::vector<EventLoop*> loops_; // 每个线程对应的EventLoop };
结合muduo源码阅读笔记(6、ExevntLoop和Thread)简单画了一下EventLoopThreadPool的架构图:
实现的伪代码:
EventLoopThreadPool::EventLoopThreadPool(EventLoop* baseLoop, const string& nameArg) : baseLoop_(baseLoop), name_(nameArg), started_(false), numThreads_(0), next_(0){ } EventLoopThreadPool::~EventLoopThreadPool(){ // Don't delete loop, it's stack variable } void EventLoopThreadPool::start(const ThreadInitCallback& cb){ assert(!started_); baseLoop_->assertInLoopThread(); 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()); // 启动线程 } if (numThreads_ == 0 && cb){ cb(baseLoop_); } } EventLoop* EventLoopThreadPool::getNextLoop(){ // round-robin算法做负载均衡 baseLoop_->assertInLoopThread(); assert(started_); EventLoop* loop = baseLoop_; // 线程数为0,就让baseLoop返回 if (!loops_.empty()){ // round-robin loop = loops_[next_]; ++next_; if (implicit_cast<size_t>(next_) >= loops_.size()){ next_ = 0; } } return loop; } EventLoop* EventLoopThreadPool::getLoopForHash(size_t hashCode){ // hash散列做负载均衡 baseLoop_->assertInLoopThread(); EventLoop* loop = baseLoop_;// 线程数为0,就让baseLoop返回 if (!loops_.empty()){ loop = loops_[hashCode % loops_.size()]; } return loop; } std::vector<EventLoop*> EventLoopThreadPool::getAllLoops(){ baseLoop_->assertInLoopThread(); assert(started_); if (loops_.empty()){ return std::vector<EventLoop*>(1, baseLoop_); }else{ return loops_; } }
细节明细
疑问:
关于EventLoopThreadPool::getNextLoop()
、EventLoopThreadPool::getLoopForHash
的作用?
解答:
小到线程之间,大到服务器集群之间,都需要保证负载均衡,以免大量的连接集中在某一个线程或者某一台机器,导致压力过大,而使连接任务无法有效处理。
本章完结
分类:
Muduo源码阅读笔记
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通