EventLoopThreadPool类
- EventLoopThreadPool是事件循环线程池,管理所有客户端连接,每个线程都有唯一一个事件循环。可以调用setThreadNum设置线程的数目。
- EventLoopThreadPool类又叫IO线程池类,由1个主线程+N个子线程组成,“1+N”的模式一般用在服务端,主线程用于接收所有客户端的连接请求,各子线程用于处理多个客户端的IO事件。给线程池分配客户端的时候采取循环分配的方式,保证线程池的负载平衡。多个客户端的IO操作可以对应于1个IO线程,但是1个客户端的IO操作不能对应于多个IO线程,因为多个IO线程抢占执行同一个客户端的读写操作会因为可能导致串写而需要用互斥锁。
- EventLoopThread作为EventLoopThreadPool的成员对象,多个EventLoopThread对象保存到std::vector中构成了EventLoopThreadPool的线程池。
数据成员:
EventLoop* baseLoop_:与Acceptor所属EventLoop相同,负责监听
bool started_:线程池是否启动
int numThreads_:线程数
int next_:新连接到来,所选择的EventLoop对象下标,选择一个线程进行处理
boost::ptr_vector<EventLoopThread> threads_:IO线程列表
std::vector<EventLoop*> loops_:EventLoop列表
typedef
typedef boost::function<void(EventLoop*)> ThreadInitCallback
成员函数:
EventLoopThreadPool(EventLoop* baseLoop):构造函数
~EventLoopThreadPool():析构函数
void setThreadNum(int numThreads):设置线程池中线程数目的大小
void start(const ThreadInitCallback& cb = ThreadInitCallback()):启动线程池
EventLoop* getNextLoop():当一个新连接到来时,选择一个新的EventLoop来处理
EventLoopThreadPool.h
// This is an internal header file, you should not include this.
#ifndef MUDUO_NET_EVENTLOOPTHREADPOOL_H
#define MUDUO_NET_EVENTLOOPTHREADPOOL_H
#include <muduo/base/Condition.h>
#include <muduo/base/Mutex.h>
#include <vector>
#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
namespace muduo
{
namespace net
{
class EventLoop;
class EventLoopThread;
class EventLoopThreadPool : boost::noncopyable
{
public:
typedef boost::function<void(EventLoop*)> ThreadInitCallback;
EventLoopThreadPool(EventLoop* baseLoop);
~EventLoopThreadPool();
//设置线程池中线程数目的大小
void setThreadNum(int numThreads) { numThreads_ = numThreads; }
//启动线程池
void start(const ThreadInitCallback& cb = ThreadInitCallback());
//当一个新连接到来时,选择一个新的EventLoop来处理
EventLoop* getNextLoop();
private:
// 与Acceptor所属EventLoop相同,负责监听
EventLoop* baseLoop_;
// 线程池是否启动
bool started_;
// 线程数
int numThreads_;
// 新连接到来,所选择的EventLoop对象下标,选择一个线程进行处理
int next_;
// IO线程列表
boost::ptr_vector<EventLoopThread> threads_;
// EventLoop列表
std::vector<EventLoop*> loops_;
};
}
}
#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 <boost/bind.hpp>
using namespace muduo;
using namespace muduo::net;
EventLoopThreadPool::EventLoopThreadPool(EventLoop* baseLoop)
: baseLoop_(baseLoop),
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)
{
EventLoopThread* t = new EventLoopThread(cb);
threads_.push_back(t);
loops_.push_back(t->startLoop()); // 启动EventLoopThread线程,在进入事件循环之前,会调用cb
}
if (numThreads_ == 0 && cb)
{
// 只有一个EventLoop,在这个EventLoop进入事件循环之前,调用cb
cb(baseLoop_);
}
}
EventLoop* EventLoopThreadPool::getNextLoop()
{
baseLoop_->assertInLoopThread();
EventLoop* loop = baseLoop_;
// 如果loops_为空,则loop指向baseLoop_
// 如果不为空,按照round-robin(RR,轮叫)的调度方式选择一个EventLoop
if (!loops_.empty())
{
// round-robin
loop = loops_[next_];
++next_;
if (implicit_cast<size_t>(next_) >= loops_.size())
{
next_ = 0;
}
}
return loop;
}