类图:
可以看出大概的关系
Channel负责注册删除和响应的IO事件,具有IO当前状态,持有相关的回调函数
EventLoop具有事件循环能力,从Poller中不停的读取IO事件,反馈到Channel上,执行Channel的回调函数
Poller持有Channel的map结构,形式为<int fd,Channel*>,其派生类会新增相关文件描述符集合(用于从系统调用中读取相关IO事件)
EventLoop.cpp
wakeupChannel_->setReadCallback( boost::bind(&EventLoop::handleRead, this)); // we are always reading the wakeupfd wakeupChannel_->enableReading();
在构造函数中进行IO事件注册,wakeupChannel用于线程唤醒,当其他线程要关闭当前线程Loop时,调用quit函数,使用wakeupChannel发送数据,阻塞在poller_->poll(kPollTimeMs, &activeChannels_);时候就会获得返回并执行下去,退出while循环
while (!quit_) { activeChannels_.clear(); //清理活跃中的IO通道 pollReturnTime_ = poller_->poll(kPollTimeMs, &activeChannels_); //等待Poller将活跃的IO通道传送过来 ++iteration_; if (Logger::logLevel() <= Logger::TRACE) { printActiveChannels(); //输出通道 } // TODO sort channel by priority eventHandling_ = true; //处理事件状态 for (ChannelList::iterator it = activeChannels_.begin(); //遍历每个IO通道处理相关事件 it != activeChannels_.end(); ++it) { currentActiveChannel_ = *it; currentActiveChannel_->handleEvent(pollReturnTime_); } currentActiveChannel_ = NULL; eventHandling_ = false; doPendingFunctors(); }
void EventLoop::updateChannel(Channel* channel) //更新Poller中Channel对应文件描述符状态 { assert(channel->ownerLoop() == this); assertInLoopThread(); poller_->updateChannel(channel); }
Channel.h和Channel.cpp
EventLoop* loop_; //持有事件循环指针 const int fd_; //持有文件描述符ID int events_; //感兴趣的事件 int revents_; // it's the received event types of epoll or poll 获得的事件反馈 int index_; // used by Poller. EPoller中代表当前IO活动状态,Poller中代表当前IO所在Poller文件描述符数组的下标位置 bool logHup_; boost::weak_ptr<void> tie_; bool tied_; bool eventHandling_; bool addedToLoop_; ReadEventCallback readCallback_; //事件回调函数 EventCallback writeCallback_; EventCallback closeCallback_; EventCallback errorCallback_;
void Channel::handleEvent(Timestamp receiveTime) { boost::shared_ptr<void> guard; if (tied_) { guard = tie_.lock(); if (guard) { handleEventWithGuard(receiveTime); } } else { handleEventWithGuard(receiveTime); } }
void Channel::handleEventWithGuard(Timestamp receiveTime)上面是Channel调用函数的过程,根据revents的状态码执行响应的动作
Poller.h和Poller.cpp
protected: typedef std::map<int, Channel*> ChannelMap; ChannelMap channels_; // fd,Channel 集合
virtual Timestamp poll(int timeoutMs, ChannelList* activeChannels) = 0; /// Changes the interested I/O events. /// Must be called in the loop thread. virtual void updateChannel(Channel* channel) = 0; /// Remove the channel, when it destructs. /// Must be called in the loop thread. virtual void removeChannel(Channel* channel) = 0; virtual bool hasChannel(Channel* channel) const; static Poller* newDefaultPoller(EventLoop* loop);几个派生类需要实现的函数,EventLoop通过基类指针调用派生类函数