class

作者: Supreme_DJK | 来源:发表于2018-11-21 19:07 被阅读0次

    Reactor模式

          它要求主线程(I/O处理单元,项目中是server类)只负责监听文件描述符上是否有事件发生,有的话就立即通知工作线程(逻辑单元),除此之外,server类(主线程mainLoop)不做任何实质性工作.读写数据,接受新的连接,以及处理客户请求均在工作线程中完成

    工作流程(使用同步I/O模型)
    1. one loop per thread
    2. 创建threadnum个大小的线程
    3. 主线程创建监听描述符,在server类中实现了连接回调,将接受到的连接绑定到epoll事件列表中
    4. 新的连接将分配一个eventloop给其使用,实现one loop per thread
    5. 监听连接的数据可读事件

    EventLoop

          
    1.基于muduo中one loop per thread的思想,我们需要创建一个线程池,给新到来的每个连接run一个Eventloop, 在构造函数中,需要检查当前thread是否已经创建了其他EventLoop对象

    1. 在IO线程中执行用户任务回调,EventLoop::runInLoop(const Fucntor &cb);如果用户在其他线程中执行调用runInLoop,cb会加入队列,IO线程会被唤醒来执行这个functor
      2.1 因为IO线程平时会阻塞在IO复用函数epoll_wait的调用当中,为了能让IO线程立即执行用户回调, 通过设立wakeupFd_来唤醒IO线程
      2.2 doPendingFuctor()中通过把回调列表swap()到局部变量functors中: 1.减小临界区长度(意味着不会阻塞其他线程调用queueInLoop()来往pendingFunctors中添加新的回调); 2.避免了死锁(添加回调时可能会再调用queueInLoop, 而对于pendingFunctors需要加锁操作)

    Epoller

    1. IO复用的封装,其owner EventLoop在IO线程中调用,无需加锁。生命期与EventLoop相等。Epoller不拥有Channel,Channel在析构的时候必须自己unregister,避免出现空悬指针
    2. 不能一边Epoller::poll()一边Channel::handleEvents(),因为后者会添加或者删除Channel,从而造成其在poll的过程中出现Channellist大小改变的情况;让Epoller::poll()只负责IO复用,不负责事件分发(dispatching)

    Channel

    1. 每个Channel从属于一个EventLoop中,在构造函数中通过绑定EventLoop和connfd来构建一个新的Channel,负责该connfd的IO事件的分发
    2. events_是channel关心的IO事件,由用户设置
    3. revents_是目前活动的事件,由EventLoop/Epoller设置
    4. Channel并不拥有该connfd,在析构时也不会关闭该connfd

    相关文章

      网友评论

          本文标题:class

          本文链接:https://www.haomeiwen.com/subject/qsucqqtx.html