目录
一、目的
EventLoop模块与线程是一一对应的
EventLoop实例化的对象在构造的时候就会初始化_thread_id
而后边当运行一个操作的时候判断当前是否运行在eventloop模板对应的线程中,就是将线程ID与EventLoop模板中的thread_id进行一个比较,相同就表示在同一个线程,不同就表示当前运行线程并不是EventLoop线程
二、含义
EventLoop模板在实例化对象的时候必须在线程内部,EventLoop实例化对象时会设置自己的thread_id,如果我们先创建多个EventLoop对象,然后创建了多个线程,将各个线程的id,重新给Event Loop进行设置 存在问题,在构造EventLoop对象,到设置新的thread_id期间将是不可控的,因此我们必须先创建线程,然后再线程的入口函数中,去实例化EventLoop对象
所以我们构造一个新模块:LoopThread
三、功能
将EventLoop与thread整合到一起
思想:
1、创建线程
2、在线程中实例化EventLoop对象(可以向外部返回实例化的EventLoop)
四、成员变量
条件变量(用于实现_loop获取的同步关系避免线程创建,但是_loop还没有去实例化之前获取_loop*)
互斥锁
线程id
EventLoop指针变量,这个对象需要在线程内部实例化

五、成员函数
构造
创建线程,设定线程入口地址

线程入口地址

获取Loop指针
如果loop为NULL就一直阻塞

六、Loopthread
1、目的
对所有的LoopThread进行管理及分配
2、功能
1、线程数量课配置
注意事项:在服务器中,主从Reactor模型是主线程只负责新连接的获取,从属线程负责链接的事件监控及处理
因此当前的线程池有可能从属线程会数量为0,也就是实现单Reactor服务器,一个线程负责获取链接,也负责链接的处理
2、对所有的线程进行管理,其实就是管理0个或多个LoopThread对象
3、提供线程分配的功能
当主线程获取一个新连接,需要将新连接挂到从属线程上进行事件监控及处理
假设有0个从属线程,则直接分配给主线程的EventLoop进行处理,假设有多个从属线程则采用RR轮思想,进行线程的分配(将对应线程的EventLoop获取到,设置给对应的Connection)
3、成员变量
从属线程的数量
保存所有的LoopThreadPool
EventLoop运行在主线程从属线程数量为0,所有的操作都在baseLoop中进行
从属线程数量大于0则从_loops中进行EventLoop分配
下一个线程id

4、成员函数
构造

设置线程的数量

创建所有从属线程

下一个线程
cpp
class LoopThread
{
private:
std::mutex _mutex;
std::condition_variable _cond;
std::thread _thread;
EventLoop *_loop;
void ThreadEntry()
{
EventLoop loop;
{
std::unique_lock<std::mutex> lock(_mutex);
_loop = &loop;
_cond.notify_all();
}
loop.Start();
}
public:
LoopThread() : _loop(NULL), _thread(std::thread(&LoopThread::ThreadEntry, this))
{
}
EventLoop *GetLoop()
{
EventLoop *loop = NULL;
{
std::unique_lock<std::mutex> lock(_mutex);
_cond.wait(lock, [&]()
{ return _loop != NULL; });
loop = _loop;
}
return loop;
}
};
class LoopThreadPool
{
private:
int _thread_cout;
std::vector<LoopThread *> _threads;
EventLoop *_baseloop;
std::vector<EventLoop *> _loops;
int _next_loop_idx;
public:
LoopThreadPool(EventLoop *baseloop) : _thread_cout(0), _next_loop_idx(0), _baseloop(baseloop)
{
}
void SetThreadCount(int cout)
{
_thread_cout = cout;
}
void Creat()
{
if (_thread_cout > 0)
{
_threads.resize(_thread_cout);
_loops.resize(_thread_cout);
for (int i = 0; i < _thread_cout; i++)
{
_threads[i] = new LoopThread();
_loops[i] = _threads[i]->GetLoop();
}
return;
}
}
EventLoop *NextLoop()
{
if (_thread_cout == 0)
return _baseloop;
_next_loop_idx = (_next_loop_idx + 1) % _thread_cout;
return _loops[_next_loop_idx];
}
};
