目录
模块设计
模块实现
模块设计
一个EventLoopThread模块是一个从属EventLoop线程,而我们的主从Reactor模型可能会存在多个从属Reactor线程,那么为了便于管理,我们可以将其封装成一个线程池,便于我们管理或者一次性启动这些从属的Reactor线程。
那么这个模块内需要哪些成员呢? 首先需要保存多个EventLoopThread对象,所以需要一个vector来保存这些对象,其次还需要一个变量用来保存从属线程数量。同时,未来我们的TcpServer需要获取到从属线程的EventLoop*指针,而我们也直到,要从EventLoopThread中获取这个指针需要加锁,如果每一次获取的时候都加锁获取,那么效率不够高,所以我们可以直接使用一个vector将所有的从属线程的EventLoop的指针直接保存起来。TcpServer只负责EventLoopThreadPool中获取一个指针分配给新连接,不会关心负载均衡的问题,所以在EventLoopThreadPool中我们需要完成负载均衡的工作,最简单的就是使用一个变量作为下一次返回的EventLoop在vector中的下标,每次获取之后都进行++,那么就相当于使用轮转的方式保证了负载均衡。
同时,还是那个问题,从属Reactor线程的数量有可能为 0 ,这时候退化为了单Reactor模型,也就是一个Reactor线程处理所有的操作,那么这时候也需要一个主Reactor线程对应的EventLoop对象,所以我们还需要一个主Reactor线程的指针。这个主Reactor其实就是我们的主线程。
class EventLoopThreadPool //Reactor模型线程池
{
private:size_t _thread_cnt; //从属Reactor线程数量EventLoop* _base_loop; //主Reactor线程的EventLoopstd::vector<EventLoopThread*> _pool; //从属线程池 , 这里不要直接适用对象,而是存储线程对象的指针更好,因为EventLoopThread不支持拷贝构造std::vector<EventLoop*> _loops; //从属Reactor线程的EventLoop对象集合uint64_t _loops_idx; //下一次分配的EventLoop*的下标
这里注意的一个细节就是,我们存储的线程对象,并不是存储对象本身,而是存储他的指针,未来在开始创建线程的时候才会真正创建对象。 因为存储对象本身的话,未来在resize的时候,时会有问题的,EventLoopThread中的成员都是不可拷贝的。
那么他需要提供哪些接口呢?
首先,需要提供接口用于设置从属线程数量
其次,需要提供接口启动线程池
还需要一个接口用于分配EventLoop,也就是返回一个EventLoop*给TcpServer用于给新连接绑定EventLoop对象。
public:EventLoopThreadPool();void SetThreadCount(); //设置从属线程数量void Start(); //启动线程池EventLoop* GetEventLoop(); //分配从属EventLoop*
模块实现
构造函数:
EventLoopThreadPool(EventLoop* loop):_thread_cnt(0),_base_loop(loop),_loops_idx(0){}
注意这个主Reactor线程是在TcpServe创建的,后续在构造EventLoopThreadPool中传入进来作为基础的EventLoop。
设置线程数量以及启动线程也都很简单。
void SetThreadCount(size_t cnt){_thread_cnt = cnt;} //设置从属线程数量void Start() //启动线程池{_pool.resize(_thread_cnt); _loops.resize(_thread_cnt);//获取EventLoop指针for(int i =0 ;i < _thread_cnt ; ++i){//创建对象_pool[i] = new EventLoopThread();_loops[i] = _pool[i]->GetEventLoop(); }}
最后就是分配EventLoop对象:
EventLoop* GetEventLoop() //分配从属EventLoop*{if(_thread_cnt == 0) return _base_loop;return _loops[(_loops_idx++)%_thread_cnt];}
这样简单的EventLoopThreadPool就设计完了
这个模块的代码其实也不好测试,我们后续设计完整个服务器模块之后再来一起测试。