• handy源码阅读(五):PollerBase类


    使用poll内核函数等待事件发生:

    struct PollerBase: private noncopyable {
      int64_t id_;
      int lastActive_;
      PollerBase(): lastActive_(-1) {
        static std::atomic<int64_t> id(0);
        id_ = ++id;
      }
    
      virtual void addChannel(Channel* ch) = 0;
      virtual void removeChannel(Channel* ch) = 0;
      virtual void updateChannel(Channel* ch) = 0;
      virtual ~PollerBase() {};
    };

    struct PollerEpoll : public PollerBase {
    int fd_;
    std::set<Channel*> liveChannels_;
    struct epoll_event activeEvs_[kMaxEvents];

    PollerEpoll();
    ~PollerEpoll();
    void addChannel(Channel* ch) override;
    void removeChannel(Channel* ch) override;
    void updateChannel(Channel* ch) override;
    void loop_once(int waitMs) override;
    };

     pollerEpoll的实现主要是使用了epoll类函数。

    PollerBase* createPoller() {
      return new PollerEpoll();
    }
    
    PollerEpoll::PollerEpoll() {
      fd_ = epoll_create1(EPOLL_CLOEXEC);  //创建一个epoll文件描述符
    }

    PollerEpoll::~PollerEpoll() {
    while (liveChannels_.size()) {
    (*liveChannels_.begin())->close(); //从poller中移除该通道,关闭通道上的文件描述符并处理该通道上的读事件。
    }
    ::close(fd_); //关闭epoll文件描述符
    }

    void PollerEpoll::addChannel(Channel* ch) {
    struct epoll_event ev;
    memset(&ev, 0, sizeof(ev));
    ev.events = ch->events();
    ev.data.ptr = ch;
    int r = epoll_ctl(fd_, EPOLL_CTL_ADD, ch->fd(), &ev); //将通道内的文件描述符和其关心的事件添加到epoll监听中。
     liveChannels_.insert(ch);
    }

    void PollerEpoll::updateChannel(Channel* ch) {
    struct epoll_event ev;
    memset(&ev, 0, sizeof(ev));
    ev.events = ch->events();
    ev.data.ptr = ch;
    int r = epoll_ctl(fd_, EPOLL_CTL_MOD, ch->fd(), &ev);
    }

    void PollerEpoll::removeChannel(Channel* ch) {
    liveChannels_.erase(ch);
    for (int i = lastActive_; i >= 0; i--) {
    if (ch == activeEvs_[i].data.ptr) {
    activeEvs_[i].data.ptr = NULL;
    break;
    }
    }
    }

    //核心函数
    void PollerEpoll::loop_once(int waitMs) {
    lastActive_ = epoll_wait(fd_, activeEvs_, kMaxEvents, waitMs);
    while (--lastActive_ >= 0) {
    int i = lastActive_;
    Channel* ch = (Channel*)activeEvs_[i].data.ptr;
    int events = activeEvs_[i].events;
    if (ch) {
    if (events & kWriteEvent) {
    ch->handleWrite();
    }
    if (events & (kReadEvent | POLLERR)) {
    ch->handleRead();
    }
    if (!(events & (kReadEvent | kWriteEvent | POLLERR))) {
    fatal("unexpected poller events");
    }
    }
    }
    }
  • 相关阅读:
    投资理财的方式
    创造新的行业需要经历四个时期
    django 架构最佳实践相关整理
    Tornado 框架使用详解, 从懵逼到开撸
    wsl 安装 Ubuntu18.04 以及 docker
    ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
    多测师拱墅校区肖sir_高级金牌讲师_第二个月基本情况
    多测师拱墅校区肖sir_高级金牌讲师_python 的基本运用
    多测师拱墅校区肖sir_高级金牌讲师_html
    多测师拱墅校区肖sir_高级金牌讲师_python 安装和pycharm
  • 原文地址:https://www.cnblogs.com/sssblog/p/11612562.html
Copyright © 2020-2023  润新知