手写muduo库(Thread)

65 阅读1分钟

EventLoopThreadPool:事件循环的线程池,管理事件循环调度

image.png 点进去EventLoopThreadPool,看到

image.png

image.png 打包了一个eventloop和一个线程
我们再进去Thread里面

image.png 就是底层的Thread,我们用C++11精简. 我们分别实现上面的3个类,从小到大输出

Thread线程类

Thread.h

#pragma once

#include "noncopyable.h"

#include<functional>
#include<thread>
#include<memory>
#include<string>
#include<atomic>

class Thread : noncopyable
{
public:
    using ThreadFunc = std::function<void()>;//线程函数的函数类型  绑定器和函数对象,就可以传参 

    explicit Thread(ThreadFunc,const std::string &name = std::string());
    ~Thread();

    void start();
    void join();

    bool started() const { return started_; }
    pid_t tid() const { return tid_;}
    const std::string& name() const { return name_; }

    static int numCreated() { return numCreated_; }
private:
    void setDefaultName();

    bool started_;//启动当前线程 
    bool joined_;//当前线程等待其他线程完了再运行下去 
    std::shared_ptr<std::thread> thread_;//自己来掌控线程对象产生的时机 
    pid_t tid_;
    ThreadFunc func_;//存储线程函数 
    std::string name_;//调试的时候打印 
    static std::atomic_int numCreated_;//对线程数量计数 

};

image.png

Thread.cc

#include "Thread.h"
#include "CurrentThread.h"

#include<semaphore.h>

std::atomic_int Thread::numCreated_(0);

Thread::Thread(ThreadFunc func,const std::string &name)
    :started_(false)
    ,joined_(false)
    ,tid_()
    ,func_(std::move(func))
    ,name_(name)
{
    setDefaultName();
}
Thread::~Thread()
{
    if(started_ && !joined_)//线程已经运行起来并且不是工作线程join
    {
        thread_->detach();//thread类提供的设置分离线程的方法,成了1个守护线程,当主线程结束,守护线程自动结束
    }
}

//一个Thread对象记录的就是一个新线程的详细信息
void Thread::start()
{
    started_ = true;
    sem_t sem;
    sem_init(&sem,false,0);
    thread_ = std::shared_ptr<std::thread>(new std::thread([&](){
        //获取线程的tid值
        tid_ = CurrentThread::tid();
        //加1操作
        sem_post(&sem);
        func_();//开启一个新线程专门执行该线程函数
    }));

    //这里必须等待获取上面新创建的线程的tid值
    sem_wait(&sem);//前面加1之后才能获取,才能解除阻塞
}
void Thread::join()
{
    joined_ = true;
    thread_->join();
}

//给线程设置默认的名字
void Thread::setDefaultName()
{
    int num = ++numCreated_;
    if(name_.empty())
    {
        char buf[32] = {0};
        snprintf(buf,sizeof buf,"Thread%d", num);
        name_ = buf;
    }
}