EventLoopThreadPool是IO线程对应的线程池,通过调用start函数来new EventLoopThread创建对应的线程和其loop,并将创建的保存在vector中。创建TcpConnection时,就会从EventLoopThreadPool中获取一个IO线程。
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();
void setThreadNum(int numThreads) { numThreads_ = numThreads; }
void start(const ThreadInitCallback& cb = ThreadInitCallback());
// valid after calling start()
/// round-robin
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:
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),
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_;
}
}