手写C++muduo库(EventLoopThread)

147 阅读2分钟

EventLoopThread绑定了一个loop和thread,在一个thread创建一个loop

image.png 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对象的地址