引言
本文讲解的EventLoopThreadPool类,实际上就是Multiple-Reactor模型
即:
- mainReactor用于listen新的客户端连接
- 接收到的连接,通过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));
}