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");
}
}
}
}

 

posted @ 2019-09-30 14:20  c++11  阅读(253)  评论(0编辑  收藏  举报