muduo_net代码剖析之EventLoopThreadPool(main+sub)

本文深入解析了EventLoopThreadPool类,它是基于Multiple-Reactor模型实现的,主要负责开启多个IO线程并使每个线程处于事件循环状态。文章详细介绍了其工作原理,包括mainReactor监听新连接,subReactor处理读写事件,以及提供了三种获取subEventLoop的方法。

引言

本文讲解的EventLoopThreadPool类,实际上就是Multiple-Reactor模型
即:

  1. mainReactor用于listen新的客户端连接
  2. 接收到的连接,通过RR方式选择并按插在subReactor上,由subReactor处理该连接的读写事件

总结一句话:EventLoopThreadPool的功能是开启若干个IO线程,并让每一个IO线程都处于事件循环状态
在这里插入图片描述

EventLoopThreadPool.h头文件
class EventLoop;
class EventLoopThread;

class EventLoopThreadPool : noncopyable
{
 public:
  typedef std::function<void(EventLoop*)> ThreadInitCallback;
  //构造、析构函数
  EventLoopThreadPool(EventLoop* baseLoop, const string& nameArg);
  ~EventLoopThreadPool();
  
  //设置subEventLoop个数
  void setThreadNum(int numThreads) { numThreads_ = numThreads; }
  
  //创建numThreads个subEventLoop,并开启它们的loop()
  void start(const ThreadInitCallback& cb = ThreadInitCallback());

  //获取EventLoop的3种方法
  EventLoop* getNextLoop(); //RR
  EventLoop* getLoopForHash(size_t hashCode);//HashCode
  std::vector<EventLoop*> getAllLoops(); //全部获取

  bool started() const //是否已经启动
  { return started_; }

  const string& name() const //EventLoopThreadPool的name
  { return name_; }

private:
  EventLoop* baseLoop_; //mainLoop
  string name_;
  bool started_;
  int numThreads_; //subEventLoop个数
  int next_; //新连接到来,所选择的EventLoop对象下标
  std::vector<std::unique_ptr<EventLoopThread>> threads_; //IO线程列表
  std::vector<EventLoop*> loops_; //EventLoop列表
};
构造函数

创建事件循环baseLoop(即mainEventLoop)

EventLoopThreadPool::EventLoopThreadPool(EventLoop* baseLoop, const string& nameArg)
  : baseLoop_(baseLoop),  //mainEventLoop
    name_(nameArg),
    started_(false),
    numThreads_(0),  //subEventLoop的个数
    next_(0)
{
}
start()

功能:创建numThreads个线程,每个线程都创建一个subEventLoop,并开启它们的loop()

void EventLoopThreadPool::start(const ThreadInitCallback& cb)
{
  assert(!started_);
  baseLoop_->assertInLoopThread();
  started_ = true;

//case 1:numThreads_>0 ⇒ 
  //创建numThreads_个线程,每个线程都创建一个事件循环
  for (int i = 0; i < numThreads_; ++i) 
  {
    char buf[name_.size() + 32];
    snprintf(buf, sizeof buf, "%s%d", name_.c_str(), i);
    //创建子线程,并在子线程中创建[事件循环loop]
    EventLoopThread* t = new EventLoopThread(cb, buf); 
    //保存[EventLoopThread*]
    threads_.push_back(std::unique_ptr<EventLoopThread>(t)); 
    //开启每个事件循环,保存[EventLoop*]
    loops_.push_back(t->startLoop()); //子线程都开始循环loop.loop()
  }

//case 2:numThreads_=0 ⇒ 没创建subEventLoop
  //EventLoopThreadPool退化成EventLoopThread类,仅有一个mainEventLoop
  if (numThreads_ == 0 && cb) 
  {
    cb(baseLoop_);
  }
}
获取subEventLoop的3种方法

当事件到来时,选择哪个subEventLoop去处理该事件的策略

EventLoop* getNextLoop(); //RR
EventLoop* getLoopForHash(size_t hashCode);//HashCode
std::vector<EventLoop*> getAllLoops(); //全部获取

示例代码

#include <muduo/net/EventLoopThreadPool.h>
#include <muduo/net/EventLoop.h>
#include <muduo/base/Thread.h>

#include <stdio.h>
#include <unistd.h>

using namespace muduo;
using namespace muduo::net;

void print(EventLoop* p = NULL)
{
  printf("main(): pid = %d, tid = %d, loop = %p\n",
         getpid(), CurrentThread::tid(), p);
}

void init(EventLoop* p)
{
  printf("init(): pid = %d, tid = %d, loop = %p\n",
         getpid(), CurrentThread::tid(), p);
}

int main()
{
  EventLoopThreadPool model(&loop, "three");
  model.setThreadNum(3);
  model.start(init);
  EventLoop* nextLoop = model.getNextLoop();
  
  nextLoop->runInLoop(std::bind(print, nextLoop));
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值