事件循环线程池,当需要多线程处理事件时使用。
该类的主要成员是std::vector<std::unique_ptr<EventLoopThread>> threads_,EventLoopThread启动一个线程,在其中运行EventLoop::loop()。先说下EventLoopThread。
EventLoopThread::EventLoopThread(const ThreadInitCallback& cb,
const string& name)
: loop_(NULL),
exiting_(false),
thread_(std::bind(&EventLoopThread::threadFunc, this), name),
mutex_(),
cond_(mutex_),
callback_(cb)
{
}
EventLoopThread::~EventLoopThread()
{
exiting_ = true;
if (loop_ != NULL) // not 100% race-free, eg. threadFunc could be running callback_.
{
// still a tiny chance to call destructed object, if threadFunc exits just now.
// but when EventLoopThread destructs, usually programming is exiting anyway.
loop_->quit();
thread_.join();
}
}
EventLoop* EventLoopThread::startLoop()
{
assert(!thread_.started());
thread_.start();
EventLoop* loop = NULL;
{
MutexLockGuard lock(mutex_);
while (loop_ == NULL)
{
cond_.wait();
}
loop = loop_;
}
return loop;
}
void EventLoopThread::threadFunc()
{
EventLoop loop;
if (callback_)
{
callback_(&loop);
}
{
MutexLockGuard lock(mutex_);
loop_ = &loop;
cond_.notify();
}
loop.loop();
//assert(exiting_);
MutexLockGuard lock(mutex_);
loop_ = NULL;
}
EventLoopThread类的主函数就是EventLoopThread::threadFunc(),在该类中创建了一个EventLoop的栈上对象,并运行EventLoop::loop(),正常情况下,EventLoopThread::threadFunc()永远都不会退出,所以也就不用担心在栈上创建的对象会析构。EventLoopThread::startLoop()返回创建的EventLoop对象的地址,因此使用条件变量来等待线程的创建与运行。
再看EventLoopThreadPool
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()
{
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_;
}
}
线程个数的指定不是通过构造函数,而是专门的一个函数
void setThreadNum(int numThreads) { numThreads_ = numThreads; }
EventLoopThreadPool::start()启动numThreads_个事件循环线程。
EventLoopThreadPool::getNextLoop()通过round-robin的方式返回一个EventLoop的实例,依次来为每个EventLoop实例分配任务。如果不存在多线程,那么返回的是主EventLoop实例。
EventLoopThreadPool::getLoopForHash()是以其他的计算方式返回实例,但是muduo库现在并没有使用。
EventLoopThreadPool::getAllLoops()返回所有的EventLoop实例