接着之前我们[muduo网络库]——muduo库Thread类(剖析muduo网络库核心部分、设计思想),我们接下来继续看muduo库中的EventLoopThread类,它和Thread类息息相关。
EventLoopThread类
封装了eventloop线程也就是IO线程,eventloopthread会启动自己的线程,并在里面运行eventloop::loop()。
重要成员变量
EventLoop *loop_;  //线程内部的eventloop*
bool exiting_;     //线程是否退出
Thread thread_;   //线程
std::mutex mutex_; //互斥锁
std::condition_variable cond_; //条件变量
ThreadInitCallback callback_; //线程初始化回调函数
- 作用如注释所示
重要成员函数
- 先来看看构造函数和析构函数
EventLoopThread::EventLoopThread(const ThreadInitCallback &cb ,const std::string &name): loop_(nullptr), exiting_(false), thread_(std::bind(&EventLoopThread::threadFunc,this),name), mutex_(), cond_(), callback_(cb){}
EventLoopThread::~EventLoopThread()
{exiting_ = true;if(loop_ != nullptr){loop_->quit();thread_.join();}
}
- 初始化给loop_为空,exiting_为否
- 注意thread_线程函数是threadFunc
- 析构函数中调用EventLoop::quit(),Thread::join()
- callback_设置为- cb
- 启动一个Loop
EventLoop* EventLoopThread::startLoop()
{thread_.start(); //启动底层新线程EventLoop *loop =nullptr; {std::unique_lock<std::mutex> lock(mutex_);while(loop_==nullptr){cond_.wait(lock);}loop = loop_;       }return loop;
}void EventLoopThread::threadFunc()
{EventLoop loop;if(callback_){callback_(&loop);}{std::unique_lock<std::mutex> lock(mutex_);loop_ = &loop;cond_.notify_one();}loop.loop(); //EventLoop loop => Poller.pollstd::unique_lock<std::mutex> lock(mutex_);loop_=nullptr;
}
- 首先,在startLoop中调用了Thread::start(),而这里的thread_的线程函数是threadFunc,在上一篇剖析Thread类时,我们在Thread::start(),看到了一个线程函数func_(),所以func就是构造函数中&EventLoopThread::threadFunc,this传入的,所以这里会创建线程调用threadFunc()函数,并且主线程阻塞等待EventLoop对象的创建
- 此时有两个线程在运行 一个是调用EventLoopThread::startLoop()的线程,一个是执行EventLoopThread::threadFunc()的线程 IO线程
- threadFunc是在单独的新线程里面运行的,创建一个独立的Eventloop,和上面的线程是一一对应的 one loop per thread
- 将IO线程定义好的loop传入回调
- 创建好loop了唤醒主线程,并把loop_给主线程,主线程返回IO线程创建的EventLoop对象
- 注意开始执行 loop.loop();,也就是EventLoop loop => Poller.poll,开始一个循环,知道循环结束eventloop析构,把loop_设为空。
总体来说,EventLoopThread提供了对应eventloop和thread的封装,意为I/O线程类,EventLoopThread可以创建一个IO线程,通过startLoop返回一个IO线程的loop,threadFunc中开启loop循环。
补充一下条件变量condition_variable
头文件 #include <condition_variable>
 
两种形式
- condition_variable
- condition_variable_any
 相同点:两者都能与std::mutex一起使用。
 不同点:前者仅限于与 std::mutex 一起工作,而后者可以和任何满足最低标准的互斥量一起工作,从而加上了_any的后缀。condition_variable_any会产生额外的开销。
std::condition_variable::wait()
 
当条件对象的某个 wait 函数被调用的时候,它使用 std::unique_lock(通过 std::mutex) 来锁住当前线程。通常使用 std::unique_lockstd::mutex 来等待,当前线程会一直被阻塞,直到另外一个线程在相同的 std::condition_variable 对象上调用了 notification 函数来唤醒当前线程,该函数会自动调用 lck.unlock() 释放锁,使得其他被阻塞在锁竞争上的线程得以继续执行。
std::condition_variable::wait_for()
 
可以指定一个时间段,在当前线程收到通知或者指定的时间 rel_time 超时之前,该线程都会处于阻塞状态。而一旦超时或者收到了其他线程的通知,wait_for 返回,剩下的处理步骤和 wait() 类似。
std::condition_variable::notify_one()
 
唤醒某个等待(wait)线程。如果当前没有等待线程,则该函数什么也不做,如果同时存在多个等待线程,则唤醒某个线程是不确定的(unspecified)。
std::condition_variable::notify_all()
 
唤醒所有的等待(wait)线程。如果当前没有等待线程,则该函数什么也不做。
代码地址:https://github.com/Cheeron955/mymuduo/tree/master