EventLoopThread绑定了一个loop和thread,在一个thread创建一个loop
EventLoopThread.h
#pragma once
#include "noncopyable.h"
#include "Thread.h"
#include<functional>
#include<mutex>
#include<condition_variable>
#include<string>
class EventLoop;
class EventLoopThread : noncopyable
{
public:
using ThreadInitCallback = std::function<void(EventLoop*)>;
EventLoopThread(const ThreadInitCallback& cb = ThreadInitCallback(),const std::string& name = std::string());//线程初始化的回调
~EventLoopThread();
EventLoop* startLoop();//开启循环
private:
void threadFunc();//线程函数,创建loop
EventLoop *loop_;
bool exiting_; //是否退出循环
Thread thread_;
std::mutex mutex_;
std::condition_variable cond_;
ThreadInitCallback callback_;//初始化操作
};
EventLoopThread.cc
#include "EventLoopThread.h"
#include "EventLoop.h"
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();
}
}
EventLoop* EventLoopThread::startLoop()
{
//启动底层的新线程,执行的是下发给底层线程的回调函数,也就是当前EventLoopThread的threadFunc
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和上面的线程是一一对应的,one loop per thread
EventLoop loop;
//ThreadInitCallback就是在底层起一个新线程去绑定一个loop的时候,什么事情还没做
//如果传递过ThreadInitCallback,在这里就会调用这个回调,可以把当前这个线程绑定的
//loop对象传给这个回调函数,就可以针对这个loop做一些想做的事
if(callback_)
{
callback_(&loop);
}
{
std::unique_lock<std::mutex> lock(mutex_);
loop_ = &loop;//就是运行在这个线程的loop对象
cond_.notify_one();
}
//这里面执行了EventLoop的loop函数,开启了底层的poller
//开始进入阻塞状态来监听远端用户的连接或已连接用户的读写事件
loop.loop();
std::unique_lock<std::mutex> lock(mutex_);
loop_=nullptr;
}
当我们调用EventLoopThread::startLoop的时候,底层才创建一个新线程,而这个刚刚创建的新线程需要执行一个线程函数(我们在构造成员变量thread_时传入的EventLoopThread::threadFunc()),等新创建的线程初始化成员变量EventLoopThread::loop_完成后,才会通知调用startLoop的线程访问成员变量loop_
即调用EventLoopThread::startLoop就会返回一个EventLoop对象,并且成员变量EventLoopThread::loop_也记录了该EventLoop对象的地址