Thread类
具体重点见代码注释
// Thread.h
#pragma once
#include "noncopyable.h"
#include <functional>
#include <thread>
#include <memory>
#include <unistd.h>
#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();
// Blocks the current thread until the thread identified by *this finishes its execution.
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_;
// joined_ == true,表示必须等待线程执行工作函数后才能接下去的工作
bool joined_;
std::shared_ptr<std::thread> thread_;
pid_t tid_;
ThreadFunc func_;
std::string name_;
static std::atomic_int numCreated_; // 记录产生线程的个数,给线程起名用的
};
// Thread.cc
#include "Thread.h"
#include "CurrentThread.h"
#include <semaphore.h>
// 原子变量初始化最好要这么写,不要写成 = 0,会报错,因为拷贝赋值被deleted
std::atomic_int Thread::numCreated_(0);
// 定义中不用再次出现默认值
Thread::Thread(ThreadFunc func, const std::string &name)
: started_(false)
, joined_(false)
, tid_(0)
, func_(std::move(func))
, name_(name)
{
setDefaultName();
}
Thread::~Thread()
{
if(started_ && !joined_)
{
thread_->detach(); // 设置分离线程,作为后台线程了
}
}
// 一个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();
sem_post(&sem); // 信号量资源 + 1
// 执行新线程的工作函数
func_();
}));
// 这里必须等待获取上面新建的tid值
// 防止上面tid_还是空的
sem_wait(&sem);
}
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;
}
}
EventLoopThread类
该类的主要功能是实现 one loop per thread
中,loop
和 thread
的一对一绑定,是muduo库的一大亮点。
// 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::start() 创建
EventLoopThread(const ThreadInitCallback &cb = ThreadInitCallback(),
const std::string &name = std::string());
~EventLoopThread();
EventLoop* startLoop();
private:
void threadFunc(); // 线程的执行函数
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(); // 启动底层的新线程
EventLoop *loop = nullptr;
{
std::unique_lock<std::mutex> lock(mutex_);
// 用while防止被其他线程抢走了,确保资源存在
while(loop_ == nullptr) // 等待对应的 EventLoop创建
{
cond_.wait(lock);
}
loop = loop_;
}
return loop;
}
// 在单独的新线程里运行,即thread_.start()内的func()
void EventLoopThread::threadFunc()
{
// 创建一个独立的eventloop,和上面线程一一对应
// one loop per thread
// 栈上分配
EventLoop loop;
if(callback_)
{
callback_(&loop);
}
{
std::unique_lock<std::mutex> lock(mutex_);
loop_ = &loop;
cond_.notify_one();
}
loop.loop(); // EventLoop.loop => Poller.poll
// loop 内 quit被置为true,退出loop才会到下面代码
std::unique_lock<std::mutex> lock(mutex_);
loop_ = nullptr;
}
EventLoopThreadPool类
该类主要功能是线程池,每一条 thread
对应一个 EventLoop
线程池若不自定义线程数,则所有工作都在唯一的Loop
对应线程中执行,即baseLoop_
若工作在多线程中,baseLoop_
默认以轮询方式分配Channel
给 subLoop
// EventLoopThreadPool.h
#pragma once
#include "noncopyable.h"
#include <functional>
#include <string>
#include <vector>
#include <memory>
class EventLoop;
class EventLoopThread;
class EventLoopThreadPool : noncopyable
{
public:
using ThreadInitCallback = std::function<void(EventLoop*)>;
EventLoopThreadPool(EventLoop *baseLoop, const std::string &nameArg);
~EventLoopThreadPool();
void setThreadNum(int numThreads) { numThreads_ = numThreads; }
// ???谁来调用传入cb
void start(const ThreadInitCallback &cb = ThreadInitCallback());
// 若工作在多线程中,baseLoop_默认以轮询方式分配Channel给 subLoop
EventLoop* getNextLoop();
std::vector<EventLoop*> getAllLoops();
bool started() const { return started_; }
const std::string name() const { return name_; }
private:
EventLoop *baseLoop_;
std::string name_;
bool started_;
int numThreads_;
int next_; // 轮询用的下标
std::vector<std::unique_ptr<EventLoopThread>> threads_; // pool
std::vector<EventLoop*> loops_;
};
// EventLoopThreadPool.cc
#include "EventLoopThreadPool.h"
#include "EventLoopThread.h"
#include <memory>
EventLoopThreadPool::EventLoopThreadPool(EventLoop *baseLoop, const std::string &nameArg)
: baseLoop_(baseLoop)
, name_(nameArg)
, started_(false)
, numThreads_(0)
, next_(0)
{
}
EventLoopThreadPool::~EventLoopThreadPool()
{
}
void EventLoopThreadPool::start(const ThreadInitCallback &cb)
{
started_ = true;
for(int i = 0; i < numThreads_; ++i)
{
char buf[name_.size() + 32];
snprintf(buf, sizeof buf, "%s%d", name_.c_str(), i);
//
EventLoopThread *t = new EventLoopThread(cb, buf);
threads_.push_back(std::unique_ptr<EventLoopThread>(t));
loops_.push_back(t->startLoop()); // 底层创建线程,绑定一个新的EventLoop,并返回该Loop地址
}
// 整个服务器只有一个线程,运行baseLoop
if(numThreads_ == 0 && cb)
{
cb(baseLoop_);
}
}
// 若工作在多线程中,baseLoop_默认以轮询方式分配Channel给 subLoop
EventLoop *EventLoopThreadPool::getNextLoop()
{
EventLoop *loop = baseLoop_;
if(!loops_.empty())
{
loop = loops_[next_];
++next_;
if(next_ >= loops_.size())
{
next_ = 0;
}
}
return loop;
}
std::vector<EventLoop *> EventLoopThreadPool::getAllLoops()
{
if(loops_.empty()) // 没有自定义线程数就只有一个mainLoop
{
return std::vector<EventLoop*>(1, baseLoop_);
}
else
{
loops_;
}
}