Muduo Channel事件分发

Channel事件分发

Channel.h

class Channel : noncopyable
{
 public:
  typedef std::function<void()> EventCallback;
  typedef std::function<void(Timestamp)> ReadEventCallback;

  Channel(EventLoop* loop, int fd);
  ~Channel();

    //回调的设置
  void handleEvent(Timestamp receiveTime);
  void setReadCallback(ReadEventCallback cb)
  { readCallback_ = std::move(cb); }
  void setWriteCallback(EventCallback cb)
  { writeCallback_ = std::move(cb); }
  void setCloseCallback(EventCallback cb)
  { closeCallback_ = std::move(cb); }
  void setErrorCallback(EventCallback cb)
  { errorCallback_ = std::move(cb); }

  /// Tie this channel to the owner object managed by shared_ptr,
  /// prevent the owner object being destroyed in handleEvent.
  void tie(const std::shared_ptr<void>&);

  int fd() const { return fd_; }	//返回channel关注的fd
  int events() const { return events_; }	
  void set_revents(int revt) { revents_ = revt; } // used by pollers
  // int revents() const { return revents_; }
  bool isNoneEvent() const { return events_ == kNoneEvent; }

    //使得channel关注对应的事件,并且通过update()挂在到树上监听
  void enableReading() { events_ |= kReadEvent; update(); }
  void disableReading() { events_ &= ~kReadEvent; update(); }
  void enableWriting() { events_ |= kWriteEvent; update(); }
  void disableWriting() { events_ &= ~kWriteEvent; update(); }
  void disableAll() { events_ = kNoneEvent; update(); }
  bool isWriting() const { return events_ & kWriteEvent; }
  bool isReading() const { return events_ & kReadEvent; }

  // for Poller
  int index() { return index_; }	//这个index作用是什么 记录在poll中的下标
  void set_index(int idx) { index_ = idx; }

  // for debug
  string reventsToString() const;
  string eventsToString() const;

  void doNotLogHup() { logHup_ = false; }

  EventLoop* ownerLoop() { return loop_; }
  void remove();

 private:
  static string eventsToString(int fd, int ev);

  void update();
  void handleEventWithGuard(Timestamp receiveTime);

  static const int kNoneEvent;	//在cc文件中定义
  static const int kReadEvent;
  static const int kWriteEvent;

  EventLoop* loop_;	//一个channel对应一个loop,但是一个loop有多个channel
  const int  fd_;	//channel关注的fd
  int        events_;	//用户设置关心的事件
  int        revents_; // it's the received event types of epoll or poll 当前活动的事件
  int        index_; // used by Poller.
  bool       logHup_;

  std::weak_ptr<void> tie_;
  bool tied_;
  bool eventHandling_;
  bool addedToLoop_;
  ReadEventCallback readCallback_;
  EventCallback writeCallback_;
  EventCallback closeCallback_;
  EventCallback errorCallback_;
};

构造函数

Channel::Channel(EventLoop* loop, int fd__)
  : loop_(loop),		//该Channel归那个IO线程管理,一个channel对应一个Eventloop,但是一个Eventloop对应多个channel
    fd_(fd__),			//每个Channel对应一个fd,不负责关闭
    events_(0),			//关注的事件
    revents_(0),		//从IOmultiplexing中接收到的事件类型
    index_(-1),			//在poll IO multiplexing中的序号
    logHup_(true),
    tied_(false),		//是否绑定
    eventHandling_(false),	//是否处于事件循环中
    addedToLoop_(false)
{
}

事件分发

void Channel::handleEvent(Timestamp receiveTime)
{
  std::shared_ptr<void> guard;
  if (tied_)
  {
    guard = tie_.lock();
    if (guard)
    {
      handleEventWithGuard(receiveTime);
    }
  }
  else
  {
    handleEventWithGuard(receiveTime);
  }
}


void Channel::handleEventWithGuard(Timestamp receiveTime)
{
  eventHandling_ = true;
  LOG_TRACE << reventsToString();
  if ((revents_ & POLLHUP) && !(revents_ & POLLIN))
  {
    if (logHup_)
    {
      LOG_WARN << "fd = " << fd_ << " Channel::handle_event() POLLHUP";
    }
    if (closeCallback_) closeCallback_();
  }

  if (revents_ & POLLNVAL)
  {
    LOG_WARN << "fd = " << fd_ << " Channel::handle_event() POLLNVAL";
  }

  if (revents_ & (POLLERR | POLLNVAL))
  {
    if (errorCallback_) errorCallback_();
  }
  if (revents_ & (POLLIN | POLLPRI | POLLRDHUP))
  {
    if (readCallback_) readCallback_(receiveTime);
  }
  if (revents_ & POLLOUT)
  {
    if (writeCallback_) writeCallback_();
  }
  eventHandling_ = false;
}

当channel对应的fd由事件发生时,会在poll()中被加入到队列中,然后依次调用这些fd对应的事件回调函数

Channel删除和修改fd关注的事件

接下来就是channel关注的fd的事件的修改以及删除

-----channel.cc
void Channel::update()
{
  addedToLoop_ = true;
  loop_->updateChannel(this);
}

void Channel::remove()
{
  assert(isNoneEvent());
  addedToLoop_ = false;
  loop_->removeChannel(this);
}



-----EventLoop.cc
void EventLoop::updateChannel(Channel* channel)
{
  assert(channel->ownerLoop() == this);	//判断channel是否被初始化
  assertInLoopThread();	//判断是否为IO线程
  poller_->updateChannel(channel);	//调用poller的updateChannel
}

//从IO multiplexing 中删除channel
void EventLoop::removeChannel(Channel* channel)
{
  assert(channel->ownerLoop() == this);
  assertInLoopThread();
  if (eventHandling_)	//在执行channel回调的时候,会进入此处进行断言(要删除的channel不在activeChannels_中
  						//或 currentActiveChannel_ = 待删除的channel,在回调中currentActiveChannel_ = 回调channel)
  {
    assert(currentActiveChannel_ == channel ||
        std::find(activeChannels_.begin(), activeChannels_.end(), channel) == activeChannels_.end());
  }
  poller_->removeChannel(channel);
}


-------poller_.cc
const int kNew = -1;	//不在epoll被监听,也不在channels_中
const int kAdded = 1;	//在epoll被监听
const int kDeleted = 2;	//被epoll删除了,但是还存在channels_中
    
void EPollPoller::updateChannel(Channel* channel)
{
  Poller::assertInLoopThread();
  const int index = channel->index();
  LOG_TRACE << "fd = " << channel->fd()
    << " events = " << channel->events() << " index = " << index;
  if (index == kNew || index == kDeleted)
  {
    // a new one, add with EPOLL_CTL_ADD
    int fd = channel->fd();	
    if (index == kNew)
    {	
      //channels_ 是一个 map<fd, Channel*>
      assert(channels_.find(fd) == channels_.end());	//fd 与 channel的对应关系不存在
      channels_[fd] = channel;	//以fd为key,加入map中,fd在一个进程中是唯一的
    }
    else // index == kDeleted
    {
      assert(channels_.find(fd) != channels_.end());	//在channels_还是可以找到fd
      assert(channels_[fd] == channel);	//map中fd与channel对应关系也存在
    }

    channel->set_index(kAdded);	//更新channel现在活动的事件
    update(EPOLL_CTL_ADD, channel);	//添加进入epoll_wait监听
  }
  else	//fd正在epoll中监听
  {
    // update existing one with EPOLL_CTL_MOD/DEL
    int fd = channel->fd();	
    (void)fd;
    assert(channels_.find(fd) != channels_.end());
    assert(channels_[fd] == channel);
    assert(index == kAdded);
    if (channel->isNoneEvent())
    {
      update(EPOLL_CTL_DEL, channel);	//从红黑树上删除对应的fd
      channel->set_index(kDeleted);		//更新channel现在活动的事件(需要先删除)
    }
    else
    {
      update(EPOLL_CTL_MOD, channel);
    }
  }
}

/* DEL */
void EPollPoller::removeChannel(Channel* channel)
{
  Poller::assertInLoopThread();
  int fd = channel->fd();
  LOG_TRACE << "fd = " << fd;
  assert(channels_.find(fd) != channels_.end());
  assert(channels_[fd] == channel);
  assert(channel->isNoneEvent());	//fd不关心任何事件,可以在别处看到删除一个channel都是现把它关心的事件置为空
  int index = channel->index();
  assert(index == kAdded || index == kDeleted);
  size_t n = channels_.erase(fd);	//从channels_删除 channel
  (void)n;
  assert(n == 1);

  if (index == kAdded)
  {
    update(EPOLL_CTL_DEL, channel);
  }
  channel->set_index(kNew);	//更新channel现在关心的事件
}


/* 由updateChannel/removeChannel调用,真正执行epoll_ctl()控制epoll的函数 */
void EPollPoller::update(int operation, Channel* channel)
{
  struct epoll_event event;
  memZero(&event, sizeof event);
  event.events = channel->events();	//这个channel关心的事件
  event.data.ptr = channel;			//把ptr指向这个channel(用于传递)
  int fd = channel->fd();			//获取这个channel对应的fd
  LOG_TRACE << "epoll_ctl op = " << operationToString(operation)
    << " fd = " << fd << " event = { " << channel->eventsToString() << " }";
  if (::epoll_ctl(epollfd_, operation, fd, &event) < 0)	//挂到红黑树上监听事件的发生,或者从红黑树上删除(取决于opt)
  {
    if (operation == EPOLL_CTL_DEL)	
    {
      LOG_SYSERR << "epoll_ctl op =" << operationToString(operation) << " fd =" << fd;
    }
    else
    {
      LOG_SYSFATAL << "epoll_ctl op =" << operationToString(operation) << " fd =" << fd;
    }
  }
}

loop循环

void EventLoop::loop()
{
  assert(!looping_);		//判断当前线程是否存在EventLoop
  assertInLoopThread();		//判断当前线程的EventLoop(构造函数记录了创建EventLoop的线程id)
  							//和调用该函数的线程是否为同一个
  looping_ = true;
  quit_ = false;  // FIXME: what if someone calls quit() before loop() ?
  LOG_TRACE << "EventLoop " << this << " start looping";

  while (!quit_)
  {
    activeChannels_.clear();
    pollReturnTime_ = poller_->poll(kPollTimeMs, &activeChannels_);
    ++iteration_;
    if (Logger::logLevel() <= Logger::TRACE)
    {
      printActiveChannels();	
    }
    // TODO sort channel by priority
    eventHandling_ = true;
	/*	
		保证在执行channel的回调时,channel不会被remove()删除
		和currentActiveChannel_一起确保
	*/

    for (Channel* channel : activeChannels_)
    {
      currentActiveChannel_ = channel;
      currentActiveChannel_->handleEvent(pollReturnTime_);	//执行每一个事件的回调
    }
    
    currentActiveChannel_ = NULL;
    eventHandling_ = false;
    
    doPendingFunctors();	//执行在其他线程加入的回调

  }

在一次循环,会做以下这些事情

1.从poll()中获取事件发生的channel,并且把它们放入activeChannels_中

2.依次从activeChannels_获取对应的channel,并且调用对应的回调函数

3.之后执行doPendingFunctors(),以进入这个函数时刻为准,把队列里面的函数依次执行,如果在执行这些函数时,又有新的函数添加到队列,那么会触发wakeupChannel_的可读事件(也就是唤醒IO线程)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值