muduo源码分析:Channel类

事件分发类Channel

事件分发器Channel的数据成员如下:

//定义事件类型变量
            static const int kNoneEvent;    //无事件
            static const int kReadEvent;    //可读事件
            static const int kWriteEvent;   //可写事件

            EventLoop *loop_;               //channel所属的loop
            const int fd_;                  //channel负责的文件描述符
            int events_;                    //注册的事件
            int revents_;                   //poller设置的就绪的事件
            int index_;                     //被poller使用的下标
            bool logHup_;                   //是否生成某些日志

            boost::weak_ptr<void> tie_; //
            bool tied_;
            bool eventHandling_;                //是否处于处理事件中
            bool addedToLoop_;
            ReadEventCallback readCallback_;    //读事件回调
            EventCallback writeCallback_;       //写事件回调
            EventCallback closeCallback_;       //关闭事件回调
            ReadEventCallback errorCallback_;   //错误事件回调

其中EventCallback和ReadEventCallback的声明如下:

 typedef boost::function<void()> EventCallback;        //事件回调函数对象类型
 typedef boost::function<void(Timestamp)> ReadEventCallback;    //读事件回调函数对象类型
        //处理事件
        void handleEvent(Timestamp receiveTime);

        //设置可读事件回调
        void setReadCallback(const ReadEventCallback &cb)
        {
            readCallback_ = cb;
        }

        //设置可写事件回调
        void setWriteCallback(const EventCallback &cb)
        {
            writeCallback_ = cb;
        }

        //设置关闭事件回调
        void setCloseCallback(const EventCallback &cb)
        {
            closeCallback_ = cb;
        }

        //设置错误事件回调
        void setErrorCallback(const EventCallback &cb)
        {
            errorCallback_ = cb;
        }

        void tie(const boost::shared_ptr<void>&);



        //返回注册的事件
        int events()const
        {
            return events_;
        }

        //设置就绪的事件
        void set_revents(int revt)
        {
            revents_ = revt;
        }

        //判断是否注册的事件
        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;
        }

Channel的主要功能为管理各种注册给poller的套接字描述符及其上发生的事件,以及事件发生了调用事件的回调函数。

Channel的主要作用如下:

1.首先我们给定Channel所属的loop以及其要处理的fd
2.接着我们开始注册fd_上需要监听的事件,如果是常用事件(读写等)的话,我们可以直接调用接口enable***来注册对应fd上的事件,与之对应的是disable***用来销毁特定的事件
3.再然后我们通过set***Callback来事件发生时的回调

Channel完整代码:

Channel.h:

#ifndef MUDUO_NET_CHANNEL_H
#define MUDUO_NET_CHANNEL_H

#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>

#include <muduo/base/Timestamp.h>

namespace muduo
{
namespace net
{

class EventLoop;


class Channel : boost::noncopyable
{
 public:
  typedef boost::function<void()> EventCallback;		//事件回调
  typedef boost::function<void(Timestamp)> ReadEventCallback;	//读事件回调

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

  void handleEvent(Timestamp receiveTime);			//处理事件
  void setReadCallback(const ReadEventCallback& cb)		//设置可读事件回调
  { readCallback_ = cb; }
  void setWriteCallback(const EventCallback& cb)		//设置可写事件回调
  { writeCallback_ = cb; }
  void setCloseCallback(const EventCallback& cb)		//设置关闭事件回调
  { closeCallback_ = cb; }
  void setErrorCallback(const EventCallback& cb)		//设置错误事件回调
  { errorCallback_ = cb; }

  void tie(const boost::shared_ptr<void>&);

  int fd() const { return fd_; }
  int events() const { return events_; }			//返回注册的事件
  void set_revents(int revt) { revents_ = revt; }		// 设置发生的事件:poller中调用
  // 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
  int index() { return 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;	//无事件
  static const int kReadEvent;	//可读事件
  static const int kWriteEvent;	//可写事件

  EventLoop* loop_;				//channel所属的EventLoop
  const int  fd_;				//channel负责的文件描述符,但不负责关闭该文件描述符
  int        events_;			//注册的事件
  int        revents_;			//poller返回的就绪的事件
  int        index_;			//表示在poll的事件数组中的序号
  bool       logHup_;			//是否生成某些日志

  boost::weak_ptr<void> tie_;
  bool tied_;
  bool eventHandling_;			//是否处于处理事件中
  bool addedToLoop_;
  ReadEventCallback readCallback_;		//读事件回调
  EventCallback writeCallback_;			//写事件回调
  EventCallback closeCallback_;			//关闭事件回调
  EventCallback errorCallback_;			//错误事件回调
};

}
}
#endif  // MUDUO_NET_CHANNEL_H

Channel.cc:

#include <muduo/base/Logging.h>
#include <muduo/net/Channel.h>
#include <muduo/net/EventLoop.h>

#include <sstream>

#include <poll.h>

using namespace muduo;
using namespace muduo::net;

const int Channel::kNoneEvent = 0;
const int Channel::kReadEvent = POLLIN | POLLPRI;
const int Channel::kWriteEvent = POLLOUT;

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

void Channel::tie(const boost::shared_ptr<void>& obj)
{
  tie_ = obj;
  tied_ = true;
}

void Channel::update()			//添加事件分发器
{
  addedToLoop_ = true;
  loop_->updateChannel(this);
}

void Channel::remove()			//移除事件分发器
{
  assert(isNoneEvent());
  addedToLoop_ = false;
  loop_->removeChannel(this);
}

void Channel::handleEvent(Timestamp receiveTime)		//核心:事件处理函数
{
  boost::shared_ptr<void> guard;
  if (tied_)
  {
    guard = tie_.lock();
    if (guard)
    {
      handleEventWithGuard(receiveTime);				//调用handleEventWithGuard
    }
  }
  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;
}

string Channel::reventsToString() const
{
  return eventsToString(fd_, revents_);
}

string Channel::eventsToString() const
{
  return eventsToString(fd_, events_);
}

string Channel::eventsToString(int fd, int ev)
{
  std::ostringstream oss;
  oss << fd << ": ";
  if (ev & POLLIN)
    oss << "IN ";
  if (ev & POLLPRI)
    oss << "PRI ";
  if (ev & POLLOUT)
    oss << "OUT ";
  if (ev & POLLHUP)
    oss << "HUP ";
  if (ev & POLLRDHUP)
    oss << "RDHUP ";
  if (ev & POLLERR)
    oss << "ERR ";
  if (ev & POLLNVAL)
    oss << "NVAL ";

  return oss.str().c_str();
}

猜你喜欢

转载自blog.csdn.net/amoscykl/article/details/83552506