文章目录
EventLoopThreadPool 是一个线程池,只不过该线程池有一点特殊,该线程池中的每一个线程都要执行EventLoop进行文件描述符的监听。
此时一个线程用于管理分配线程池中的EventLoop,如果线程池为空,主线程的EventLoop用与监听所有的文件描述符
在源码中解释。
构造与析构
EventLoopThreadPool::EventLoopThreadPool(EventLoop* baseLoop, const string& nameArg)
: baseLoop_(baseLoop),
name_(nameArg),
started_(false),
//线程池的大小
numThreads_(0),
next_(0)
{
}
EventLoopThreadPool::~EventLoopThreadPool()
{
// Don't delete loop, it's stack variable
}
start 开启线程池
void EventLoopThreadPool::start(const ThreadInitCallback& cb)
{
assert(!started_);
baseLoop_->assertInLoopThread();
started_ = true;
//创建numThreads_个事件循环器
for (int i = 0; i < numThreads_; ++i)
{
char buf[name_.size() + 32];
snprintf(buf, sizeof buf, "%s%d", name_.c_str(), i);
//创建一个EventLoopThread 对象
EventLoopThread* t = new EventLoopThread(cb, buf);
threads_.push_back(std::unique_ptr<EventLoopThread>(t));
//事件循环器开始执行,如果此时需要监听的文件描述符的数量小于线程个数
//其余的线程会进入睡眠状态
loops_.push_back(t->startLoop());
}
//线程池的个数为0,则主线程开始监听套接字
if (numThreads_ == 0 && cb)
{
cb(baseLoop_);
}
}
getNextLoop 采用轮询的方式分配EventLoop
//循环获取事件循环器
//每个线程对应一个事件循环器
EventLoop* EventLoopThreadPool::getNextLoop()
{
baseLoop_->assertInLoopThread();
assert(started_);
EventLoop* loop = baseLoop_;
//如果线程池为空,返回主线程的EventLoop
if (!loops_.empty())
{
// round-robin
loop = loops_[next_];
++next_;
//循环获取,如果next_的值大于了loops_.size(), 从第一个开始获取
if (implicit_cast<size_t>(next_) >= loops_.size())
{
next_ = 0;
}
}
//返回事件循环器
return loop;
}
getLoopForHash采用hash方式分配EventLoop
//hash 的方式获取EventLoop 事件循环器
EventLoop* EventLoopThreadPool::getLoopForHash(size_t hashCode)
{
baseLoop_->assertInLoopThread();
EventLoop* loop = baseLoop_;
if (!loops_.empty())
{
//hash 的方式获取EventLoop 事件循环器
loop = loops_[hashCode % loops_.size()];
}
return loop;
}
getAllLoops 返回所有的EventLoop
//返回所有的loop
std::vector<EventLoop*> EventLoopThreadPool::getAllLoops()
{
baseLoop_->assertInLoopThread();
assert(started_);
//如果线程池为空
if (loops_.empty())
{
//将主线程的EventLoop 返回
return std::vector<EventLoop*>(1, baseLoop_);
}
else
{
//否则 返回线程池中的EventLoop
return loops_;
}
}