muduo网络库学习(八)事件驱动循环线程池EventLoopThreadPool

muduo是支持多线程的网络库,在muduo网络库学习(七)用于创建服务器的类TcpServer中也提及了TcpServer中有一个事件驱动循环线程池,线程池中存在大量线程,每个线程运行一个EventLoop::loop

线程池的作用体现在

  • 用户启动TcpServer服务器时创建大量子线程,每个子线程创建一个EventLoop并开始执行EventLoop::loop
  • 主线程的线程池保存着创建的这些线程和EventLoop
  • Acceptor接收到客户端的连接请求后返回TcpServerTcpServer创建TcpConnection用于管理tcp连接
  • TcpServer从事件驱动线程池中取出一个EventLoop,并将这个EventLoop传给TcpConnection的构造函数
  • TcpConnection创建用于管理套接字的Channel并注册到从线程池中取出的EventLoopPoller
  • 服务器继续监听

这个池子既是一个线程池,又是一个EventLoop池,二者是等价的,一个EventLoop对应一个线程
这种方式称为one loop per threadreactor + 线程池


线程池的定义比较简单,唯一复杂的地方是由主线程创建子线程,子线程创建EventLoop并执行EventLoop::loop,主线程返回创建的EventLoop给线程池并保存起来,比较绕。
线程池EventLoopThreadPool定义如下

class EventLoop;
class EventLoopThread;

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
  /* 获取一个线程(事件驱动循环),通常在创建TcpConnection时调用 */
  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:

  /* 主线程的事件驱动循环,TcpServer所在的事件驱动循环,创建TcpServer传入的EventLoop */
  EventLoop* baseLoop_;
  string name_;
  bool started_;
  /* 线程数 */
  int numThreads_;
  /* 标记下次应该取出哪个线程,采用round_robin */
  int next_;
  /* 线程池中所有的线程 */
  std::vector<std::unique_ptr<EventLoopThread>> threads_;
  /* 
   * 线程池中每个线程对应的事件驱动循环,从线程池取出线程实际上返回的是事件驱动循环
   * 每个事件驱动循环运行在一个线程中
   */
  std::vector<EventLoop*> loops_;
};

成员变量和函数没什么特别的,其中

  • baseLoop_是主线程所在的事件驱动循环,即TcpServer所在的那个主线程,这个事件驱动循环通常只负责监听客户端连接请求,即AcceptorChannel
  • 两个vector保存着所有子线程即每个子线程对应的EventLoop。事件驱动循环线程被封装在EventLoopThread中,EventLoopThread中使用的Thread才是真正的线程封装

线程池是由TcpServer启动的,在TcpServer:

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值