muduo源码分析 Channel类

文章目录

  • 头文件
  • 构造与析构
  • update与remove
  • handleEvent 事件分发

Channel 是单个文件描述符进行事件分发的类
https://blog.csdn.net/qq_43390943/article/details/89873302
中介绍了Channel在新连接到达时的作用。这里在源码中看一些Channel 处理了哪些东西。

头文件

//事件分发器,每个事件分发器对应一个文件描述符,监听该文件描述符上的所有的事件
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 对应的文件描述符
  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; }

  //注册读事件
  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
  //所有Channel 会在IO 复用类中用一个vector 管理起来,
  //index标识 当前的Channel 在那个vector 中的位置
  int index() { return index_; }
  //设置index下标
  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;	//没有事件
  static const int kReadEvent;	//读事件
  static const int kWriteEvent;	//写事件

  //事件循环loop 
  EventLoop* loop_;
  //文件描述符
  const int  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),
    fd_(fd__),
    //监听的事件
    events_(0),
    //就绪的事件
    revents_(0),
    index_(-1),
    logHup_(true),
    tied_(false),
    //事件正在处理
    eventHandling_(false),
    //正在循环监听中
    addedToLoop_(false)
{
}

Channel::~Channel()
{
  assert(!eventHandling_);
  assert(!addedToLoop_);
  if (loop_->isInLoopThread())
  {
    assert(!loop_->hasChannel(this));
  }
}

update与remove

void Channel::update()
{
  addedToLoop_ = true;
  //调用事件循环的update 函数
  //将该Channle 添加到事件循环中去
  //在事件循环中 更新当前Channel 
  loop_->updateChannel(this);
}

void Channel::remove()
{
  assert(isNoneEvent());
  addedToLoop_ = false;
  //从事件循环中删除当前的Channel 
  loop_->removeChannel(this);
}

handleEvent 事件分发

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

你可能感兴趣的:(muduo源码分析)