说明
任何一个线程,只要创建并运行了EventLoop,都称之为IO线程,为了方便使用。定义了EventLoopThread类,封装了EventLoop 和 Thread成为一个IO线程。
成员变量
重点关注:
thread_: 线程类,以及给他注册的线程函数,线程函数在栈上构造出Eventloop对象。
loop_: EventLoop实例, 线程函数栈构造出来的。在此保存,可以供TcpServer等上层类获取使用
cond_: 线程函数执行时机不确定, cond_在startLoop的时候可以等待线程函数给loop_赋值后再唤醒startLoop返回当前的loop。
EventLoop* loop_ GUARDED_BY(mutex_); //指向一个EventLoop对象,一个IO线程只有一个EventLoop对象,指向了threadFunc()函数中栈上的对象,函数退出,loop_就置为NULL了,指针失效
bool exiting_; //是否处于正在退出中,在析构函数中为true,感觉不到这个变量的用处
Thread thread_; //绑定私有线程函数threadFunc()
MutexLock mutex_;
Condition cond_ GUARDED_BY(mutex_);
ThreadInitCallback callback_; //线程初始化回调函数,在EventLoop::loop事件循环之前调用,在构造函数中赋值,传递EventLoop*参数,可以做一些初始化操作,也可以不做
方法
1. threadFunc() : 线程函数,在这里创建EventLoop对象,进入loop.loop()状态,并保存loop指针
//线程函数,在这里创建EventLoop对象,进入loop.loop()状态
void EventLoopThread::threadFunc() //bind线程函数的时候有this指针。 所以对象的成员能在这个线程访问(通过this传到此函数)
{
EventLoop loop;
if (callback_)
{
callback_(&loop);
}
{
MutexLockGuard lock(mutex_);
loop_ = &loop;
cond_.notify();
}
loop.loop();
//assert(exiting_);
MutexLockGuard lock(mutex_);
loop_ = NULL;
}
2.startLoop(): 创建线程、等待线程创建好loop对象,放回loop指针
//启动线程,该线程就称为了IO线程,也就是在线程内部创建了EventLoop对象
//断言该线程还没启动,然后调用threadFunc(),生成EventLoop对象,如果传的参数有线程初始化函数,就先调用该函数,具体看代码,也比较简单
//这时条件变量就用到了,就是要保证先给loop_变量赋值,再结束startLoop(),返回loop,否则可能返回NULL
EventLoop* EventLoopThread::startLoop()
{
assert(!thread_.started());
thread_.start(); //启动线程
//线程启动后,在线程函数中生成线程的loop
EventLoop* loop = NULL;
{
MutexLockGuard lock(mutex_);
while (loop_ == NULL)
{
cond_.wait(); //上面的 thread_.start() 开启后等待执行threadFunc完后loop_就不为空了。
}
loop = loop_;
}
return loop;
}