muduo源码剖析之EventLoopThreadPool

简介: EventLoopThreadPool是EventLoopThread类的线程池类封装了若干个EventLoopThread的线程池,所有者是一个外部的EventLoop。

简介

EventLoopThreadPool是EventLoopThread类的线程池类

封装了若干个EventLoopThread的线程池,所有者是一个外部的EventLoop

EventLoopThreadPool == EventLoopThread + vector

主要成员及属性解析

通过调用start函数来new EventLoopThread创建对应的线程和其loop,并将创建的保存在vector中

源码剖析

这个类比较简单,代码都写了注释,不多说

EventLoopThreadPool.h

// Copyright 2010, Shuo Chen.  All rights reserved.
// http://code.google.com/p/muduo/
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.

// Author: Shuo Chen (chenshuo at chenshuo dot com)
//
// This is an internal header file, you should not include this.

#ifndef MUDUO_NET_EVENTLOOPTHREADPOOL_H
#define MUDUO_NET_EVENTLOOPTHREADPOOL_H

#include "muduo/base/noncopyable.h"
#include "muduo/base/Types.h"

#include <functional>
#include <memory>
#include <vector>

namespace muduo
{
   

namespace net
{
   

class EventLoop;
class EventLoopThread;

class EventLoopThreadPool : noncopyable
{
   
 public:
  typedef std::function<void(EventLoop*)> ThreadInitCallback;

  EventLoopThreadPool(EventLoop* baseLoop, const string& nameArg);
  ~EventLoopThreadPool();

  //设置subloop的数量
  void setThreadNum(int numThreads) {
    numThreads_ = numThreads; }
  //线程池启动,会创建设置好的EventLoopThread数量,并保存threads_中
  void start(const ThreadInitCallback& cb = ThreadInitCallback());

  // valid after calling start()
  /// round-robin
  //通过next变量保存下标,每调用一次就会获取下一个loop
  EventLoop* getNextLoop();

  /// with the same hash code, it will always return the same EventLoop
  //使用相同的哈希码,它将始终返回相同的事件循环,
  //通过hash码获取相应的loop
  EventLoop* getLoopForHash(size_t hashCode);

  //获取所有的subloop
  std::vector<EventLoop*> getAllLoops();

  bool started() const
  {
    return started_; }

  const string& name() const
  {
    return name_; }

 private:

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

}  // namespace net
}  // namespace muduo

#endif  // MUDUO_NET_EVENTLOOPTHREADPOOL_H

EventLoopThreadPool.cc

// Copyright 2010, Shuo Chen.  All rights reserved.
// http://code.google.com/p/muduo/
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.

// Author: Shuo Chen (chenshuo at chenshuo dot com)

#include "muduo/net/EventLoopThreadPool.h"

#include "muduo/net/EventLoop.h"
#include "muduo/net/EventLoopThread.h"

#include <stdio.h>

using namespace muduo;
using namespace muduo::net;

//EventLoopThreadPool loop对应的线程池
EventLoopThreadPool::EventLoopThreadPool(EventLoop* baseLoop, const string& nameArg)
  : baseLoop_(baseLoop),//设置mainloop
    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()        //获取一个线程(事件驱动循环),通常在创建TcpConnection时调用 
{
   
  baseLoop_->assertInLoopThread();
  assert(started_);
  EventLoop* loop = 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)
{
   
  baseLoop_->assertInLoopThread();
  EventLoop* loop = 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_;
  }
}
目录
相关文章
|
4月前
|
API
muduo源码剖析之SocketOps类
对socket设置API的封装。比较简单,已经编写注释。
17 0
|
4月前
muduo源码剖析之Socket类
封装了一个sockfd相关的设置。比较简单,已经编写注释。
17 0
|
4月前
muduo源码剖析之InetAddress
InetAddress 类在 muduo 网络库中被广泛使用,用于表示网络中的通信实体的地址信息,例如服务器地址、客户端地址等。通过 InetAddress 类,我们可以方便地操作 IP 地址和端口号,实现网络通信的功能。InetAddress 类是 muduo 网络库中的一个重要类,用于表示网络中的 IP 地址和端口号。源码比较简单,已经编写详细注释。
34 0
|
4月前
|
安全 API
muduo源码剖析之EventLoop事件循环类
EventLoop.cc就相当于一个reactor,多线程之间的函数调用(用eventfd唤醒),epoll处理,超时队列处理,对channel的处理。运行loop的进程被称为IO线程,EventLoop提供了一些API确保相应函数在IO线程中调用,确保没有用互斥量保护的变量只能在IO线程中使用,也封装了超时队列的基本操作。
41 0
|
4月前
muduo源码剖析之Acceptor监听类
Acceptor类用于创建套接字,设置套接字选项,调用socket()->bind()->listen()->accept()函数,接受连接,然后调用TcpServer设置的connect事件的回调。listen()//在TcpServer::start中调用封装了一个listen fd相关的操作,用于mainLoop接受器封装,实质上就是对Channel的多一层封装监听连接 当新连接进入时,调用Socket::accept创建套接字,触发TcpServer的回调TcpServer通过该接口设置回调,
24 0
|
4月前
|
前端开发
muduo源码剖析之AsyncLogging异步日志类
AsyncLogging是muduo的日志,程序如果直接让文件写日志可能会发生阻塞,muduo前端设计了2个BufferPtr,分别是currentBuffer_和nextBuffer_,还有一个存放BufferPtr的vector(buffers_)。多个前端线程往currentBuffer_写数据,currentBuffer_写满了将其放入buffers_,通知后端线程读。前端线程将currentBuffer_和nextBuffer_替换继续写currentBuffer_。
27 0
|
4月前
muduo源码剖析之EventLoopThread
EventLoopThread类包装了一个thread类和一个EventLoop类,(one loop per thread)是封装了一个EventLoop的独立线程。
21 0
|
4月前
|
安全 C++ 容器
muduo源码剖析之TimerQueue类
通过timerfd实现的定时器功能,为EventLoop扩展了一系列runAt,runEvery,runEvery等函数TimerQueue中通过std::set维护所有的Timer,也可以使用优先队列实现muduo的TimerQueue是基于timerfd_create实现,这样超时很容易和epoll结合起来。等待超时事件保存在set集合中,注意set集合的有序性,从小到大排列,整个对TimerQueue的处理也就是对set集合的操作。
18 0
muduo源码剖析之TimerQueue类
|
4月前
|
API
muduo源码剖析之poller/EpollPoller多路复用类
poller是I/O多路复用接口抽象虚基类,对I/O多路复用API的封装,muduo提供了EPollPoller和PollPoller派生类(epoll和poll),所以不支持select.newDefaultPoller()默认选择epoll。
38 0
|
4月前
|
网络协议
muduo源码剖析之TcpClient客户端类
muduo用TcpClient发起连接,TcpClient有一个Connector连接器,TCPClient使用Conneccor发起连接, 连接建立成功后, 用socket创建TcpConnection来管理连接, 每个TcpClient class只管理一个TcpConnecction,连接建立成功后设置相应的回调函数。很显然,TcpClient用来管理客户端连接,真正连接交给Connector。
28 0
muduo源码剖析之TcpClient客户端类