目录
EventLoopThread::EventLoopThread
EventLoopThread::~EventLoopThread()
EventLoopThread事件线程类
对EventLoop和thread的封装,一个线程中有一个loop,通过绑定器将其绑定。
成员变量:

成员函数:
EventLoopThread::EventLoopThread

对一些成员变量进行初始化,要注意的是,这里将线程通过bind绑定器绑定一个threadFunc回调函数,在该构造函数中并不会立即创建新线程,实际的线程执行是在后续startLoop函数中调用thread的start函数才进行执行的。
EventLoopThread::~EventLoopThread()

startLoop()和threadFunc():
EventLoop* EventLoopThread::startLoop()//开启循环
{
thread_.start();//启动底层的新线程
//启动后执行的是EventLoopThread::threadFunc
EventLoop *loop = nullptr;
{
std::unique_lock<std::mutex> lock(mutex_);
while ( loop_ == nullptr )
{
cond_.wait(lock);//挂起,等待 threadFunc中的loop创建好并通知
}
loop = loop_;
}
return loop;
}
void EventLoopThread::threadFunc()
{
EventLoop loop;//创建一个独立的eventloop,和上面的线程是一一对应的,one loop per thread
if (callback_)//如果有回调
{
callback_(&loop);//绑定loop做一些事情
}
{
std::unique_lock<std::mutex> lock(mutex_);
loop_ = &loop;//就是运行在这个线程的loop对象
cond_.notify_one();//唤醒1个线程
}
// 一般来说会一直在loop函数中循环
loop.loop();//相当于EventLoop loop => Poller.poll
//执行到这个下边就说明服务器程序要关闭掉了
std::unique_lock<std::mutex> lock(mutex_);
loop_ = nullptr;
}
❤这两个函数要放到一起说:
1. 首先在startLoop函数中,调用thread_.start(),启动新线程去执行在EventLoop构造函数中绑定的threadFunc函数;
2. 在startLoop函数中,创建一个EventLoop对象loop初始化为nullptr;
3. 进入一个作用域,unique_lock<std::mutex> lock(mutex_)创建互斥锁;
4. while循环检查loop_是否为nullptr,如果为空,调用cond_.wait(lock)挂起,等待其他线程通过调用cond.notufy_one()唤醒,继续执行;
5. 其他线程调用cond.notufy_one()后,while循环退出,将loop_赋值给loop,返回loop,也即返回新线程中创建的Eventloop对象;
6. 在threadFunc函数中,首先创建一个EventLoop对象,loop,每个线程都用有一个独立的EventLoop;
7. 如果存在callback_,则调用callback_(&loop)去执行回调函数;
8. 进入一个作用域,unique_lock<std::mutex> lock(mutex_)创建互斥锁,并将loop_设置为当前loop,即将新线程中创建的EventLoop对象loop赋值给loop_,然后cond.notufy_one()唤醒等待中的线程。
9. 调用loop.loop()进入事件循环,执行EventLoop中的loop()函数;
10. 事件循环结束后,也就是EventLoop中的loop()函数退出后,再次获取锁,将loop_设置为nullptr,表示线程结束。
11. 返回到startLoop函数将loop返回。
该过程实现了创建一个新线程,并在新线程中运行一个独立的
EventLoop对象,并通过条件变量等待新线程中的EventLoop对象创建完成后返回,从而实现了一个 "one loop per thread" 的设计模式。
EventLoopThread.h
#pragma once
#include "noncopyable.h"
#include "Thread.h"
#include <functional>
#include <mutex>
#include <condition_variable>
#include <string>
class EventLoop;
// eventloop + thread
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()//开启循环
{
thread_.start();//启动底层的新线程
//启动后执行的是EventLoopThread::threadFunc
EventLoop *loop = nullptr;
{
std::unique_lock<std::mutex> lock(mutex_);
while ( loop_ == nullptr )
{
cond_.wait(lock);//挂起,等待 threadFunc中的loop创建好并通知
}
loop = loop_;
}
return loop;
}
//下面这个方法,start()后的执行的,也就是在单独的新线程里面运行的1
//start()运行后创建新线程,执行绑定的threadFunc函数
void EventLoopThread::threadFunc()
{
EventLoop loop;//创建一个独立的eventloop,和上面的线程是一一对应的,one loop per thread
if (callback_)//如果有回调
{
callback_(&loop);//绑定loop做一些事情
}
{
std::unique_lock<std::mutex> lock(mutex_);
loop_ = &loop;//就是运行在这个线程的loop对象
cond_.notify_one();//唤醒1个线程
}
// 一般来说会一直在loop函数中循环
loop.loop();//相当于EventLoop loop => Poller.poll
//执行到这个下边就说明服务器程序要关闭掉了
std::unique_lock<std::mutex> lock(mutex_);
loop_ = nullptr;
}
EventLoopThread是将EventLoop与线程封装在一起的类,确保每个线程拥有一个独立的EventLoop。在构造时,线程并不立即启动,而是在startLoop()被调用时启动。threadFunc()中创建EventLoop,并在回调函数callback_中处理。当startLoop()被调用时,它会等待线程创建并准备好EventLoop后返回。EventLoop的loop()函数执行直到服务器关闭。
8212

被折叠的 条评论
为什么被折叠?



