国外的域名注册网站哪个好,自助无人售货机,租赁商城手机网站开发,交通运输部: 优化交通运输领域防控最核⼼的部分就是 EventLoop 、 Channel 以及 Poller 三个类#xff0c;其中 EventLoop 可以看作是对业务线程的封装#xff0c;⽽ Channel 可以看作是对每个已经建⽴连接的封装#xff08;即 accept(3) 返回的⽂件描述符#xff09; EventLoop
class EventLoop {
p… 最核⼼的部分就是 EventLoop 、 Channel 以及 Poller 三个类其中 EventLoop 可以看作是对业务线程的封装⽽ Channel 可以看作是对每个已经建⽴连接的封装即 accept(3) 返回的⽂件描述符 EventLoop
class EventLoop {
public:typedef std::functionvoid() Function;// 初始化poller, event_fd给 event_fd 注册到 epoll 中并注册其事件处理回调EventLoop();~EventLoop();// 开始事件循环 调⽤该函数的线程必须是该 EventLoop 所在线程也就是 Loop 函数不能跨线程调⽤void Loop();// 停⽌ Loopvoid StopLoop();// 如果当前线程就是创建此EventLoop的线程 就调⽤callback(关闭连接 EpollDel) 否则就放⼊等待执⾏
函数区void RunInLoop(Function func);// 把此函数放⼊等待执⾏函数区 如果当前是跨线程 或者正在调⽤等待的函数则唤醒void QueueInLoop(Function func);// 把fd和绑定的事件注册到epoll内核事件表void PollerAdd(std::shared_ptrChannel channel, int timeout 0);// 在epoll内核事件表修改fd所绑定的事件void PollerMod(std::shared_ptrChannel channel, int timeout 0);// 从epoll内核事件表中删除fd及其绑定的事件void PollerDel(std::shared_ptrChannel channel);// 只关闭连接(此时还可以把缓冲区数据写完再关闭)void ShutDown(std::shared_ptrChannel channel);
代码随想录知识星球
从 EventLoop 的类定义中可以看出除了⼀些状态量以外每个 EventLoop 持有⼀个 Poller 的智能指针对
epoll / poll 的封装⼀个⽤于 EventLoop 之间通信的 Channel ⾃⼰的线程 id互斥锁以及装有等待处理函
数的 vector 。很明显 EventLoop 并不直接管理各个连接的 Channel ⽂件描述符的封装⽽是通过
Poller 来进⾏的。 EventLoop 中最核⼼的函数就是 EventLoop::Loop() 。bool is_in_loop_thread();
private:// 创建eventfd 类似管道的 进程间通信⽅式static int CreateEventfd();void HandleRead(); // eventfd的读回调函数(因为event_fd写了数据所以触发
可读事件从event_fd读数据)void HandleUpdate(); // eventfd的更新事件回调函数(更新监听事件)void WakeUp(); // 异步唤醒SubLoop的epoll_wait(向event_fd中写⼊数据)void PerformPendingFunctions(); // 执⾏正在等待的函数(SubLoop注册EpollAdd连接套接字以
及绑定事件的函数)
private: std::shared_ptrPoller poller_; // io多路复⽤ 分发器int event_fd_; // ⽤于异步唤醒 SubLoop 的 Loop 函数中的
Poll(epoll_wait因为还没有注册fd会⼀直阻塞)std::shared_ptrChannel wakeup_channel_; // ⽤于异步唤醒的 channelpid_t thread_id_; // 线程idmutable locker::MutexLock mutex_;std::vectorFunction pending_functions_; // 正在等待处理的函数bool is_stop_; // 是否停⽌事件循环bool is_looping_; // 是否正在事件循环bool is_event_handling_; // 是否正在处理事件bool is_calling_pending_functions_; // 是否正在调⽤等待处理的函数
}; 从 EventLoop 的类定义中可以看出除了⼀些状态量以外每个 EventLoop 持有⼀个 Poller 的智能指针对epoll / poll 的封装⼀个⽤于 EventLoop 之间通信的 Channel ⾃⼰的线程 id 互斥锁以及装有等待处理函数的 vector 。很明显 EventLoop 并不直接管理各个连接的 Channel ⽂件描述符的封装⽽是通过 Poller 来进⾏的。 EventLoop 中最核⼼的函数就是 EventLoop::Loop() 。 void EventLoop::Loop() {// 开始事件循环 调⽤该函数的线程必须是该EventLoop所在线程assert(!is_looping_);assert(is_in_loop_thread());is_looping_ true;is_stop_ false;while (!is_stop_) {// 1、epoll_wait阻塞 等待就绪事件auto ready_channels poller_-Poll();is_event_handling_ true;// 2、处理每个就绪事件(不同channel绑定了不同的callback)for (auto channel : ready_channels) {channel-HandleEvents();}is_event_handling_ false;// 3、执⾏正在等待的函数(fd注册到epoll内核事件表)PerformPendingFunctions();// 4、处理超时事件 到期了就从定时器⼩根堆中删除(定时器析构会EpollDel掉fd)poller_-HandleExpire();}is_looping_ false;
} 每个 EventLoop 对象都唯⼀绑定了⼀个线程这个线程其实就在⼀直执⾏这个函数⾥⾯的 while 循环这个 while 循环的⼤致逻辑⽐较简单。就是调⽤ Poller::poll() 函数获取事件监听器上的监听结果。接下来在 Loop ⾥⾯就会调⽤监听结果中每⼀个 Channel 的处理函数 HandlerEvent() 。每⼀个 Channel 的处理函数会 根据 Channel 中封装的实际发⽣的事件执⾏ Channel 中封装的各事件处理函数。⽐如⼀个 Channel 发⽣ 了可读事件可写事件则这个 Channel 的 HandlerEvent() 就会调⽤提前注册在这个 Channel 的可读事件 和可写事件处理函数⼜⽐如另⼀个 Channel 只发⽣了可读事件那么 HandlerEvent() 就只会调⽤提前注册在这个 Channel 中的可读事件处理函数。 从中可以看到每个 EventLoop 实际上就做了四件事 1. epoll_wait阻塞 等待就绪事件(没有注册其他fd时可以通过event_fd来异步唤醒) 2. 处理每个就绪事件 3. 执⾏正在等待的函数(fd注册到epoll内核事件表) 4. 处理超时事件到期了就从定时器⼩根堆中删除