muduo之channel
生活随笔
收集整理的這篇文章主要介紹了
muduo之channel
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
? ? ? ? ?channel是muduo中的事件分發(fā)器,它只屬于一個EventLoop,Channel類中保存著IO事件的類型以及對應(yīng)的回調(diào)函數(shù),每個channel只負責(zé)一個文件描述符,但它并不擁有這個文件描述符。channel是在epoll和TcpConnection之間起溝通作用,故也叫做通道,其它類通過調(diào)用channel的setCallbcak來和建立channel溝通關(guān)系。
Channel.h
// Copyright 2010, Shuo Chen. All rights reserved. // http://code.google.com/p/muduo/ // // Use of this source code is governed by a BSD-style license // that can be found in the License file.// Author: Shuo Chen (chenshuo at chenshuo dot com) // // This is an internal header file, you should not include this.#ifndef MUDUO_NET_CHANNEL_H #define MUDUO_NET_CHANNEL_H#include "muduo/base/noncopyable.h" #include "muduo/base/Timestamp.h"#include <functional> #include <memory>namespace muduo { namespace net {class EventLoop;/// /// A selectable I/O channel. /// /// This class doesn't own the file descriptor. /// The file descriptor could be a socket, /// an eventfd, a timerfd, or a signalfd 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) //關(guān)閉{ 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_; }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 Pollerint index() { return index_; }void set_index(int idx) { index_ = idx; }// for debugstring 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_;const int fd_;int events_;int revents_; // it's the received event types of epoll or pollint 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_; };} // namespace net } // namespace muduo#endif // MUDUO_NET_CHANNEL_HChannel.cc
// Copyright 2010, Shuo Chen. All rights reserved. // http://code.google.com/p/muduo/ // // Use of this source code is governed by a BSD-style license // that can be found in the License file.// Author: Shuo Chen (chenshuo at chenshuo dot com)#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(事件分發(fā)器),只屬于一個EventLoop,Channel類中保存著IO事件的類型以及對應(yīng)的回調(diào)函數(shù),每個channel只負責(zé)一個文件描述符 Channel::Channel(EventLoop* loop, int fd__): loop_(loop), //channel所屬的loop,一個channel只屬于一個loopfd_(fd__), //channel負責(zé)的文件描述符events_(0), //注冊的事件revents_(0), //poller設(shè)置的就緒的事件index_(-1), //被poller使用的下標logHup_(true), //是否生成某些日志tied_(false), 用于tie()方法eventHandling_(false), //處理handevent的標志addedToLoop_(false) //是否正在循環(huán)監(jiān)聽中 { }Channel::~Channel() {assert(!eventHandling_);assert(!addedToLoop_);if (loop_->isInLoopThread()){assert(!loop_->hasChannel(this));} }void Channel::tie(const std::shared_ptr<void>& obj) {tie_ = obj;tied_ = true; }void Channel::update() //調(diào)到loop_->updateChannel,再調(diào)用poll->updateChannel {addedToLoop_ = true;loop_->updateChannel(this); }void Channel::remove() //同上 {assert(isNoneEvent());addedToLoop_ = false;loop_->removeChannel(this);//移除ChannelMap里面的channel }//處理所有發(fā)生的事件,如果活著,底層調(diào)用handleEventWithGuard void Channel::handleEvent(Timestamp receiveTime) 事件到來調(diào)用handleEvent處理 {std::shared_ptr<void> guard; //守護if (tied_){guard = tie_.lock();if (guard){handleEventWithGuard(receiveTime);}}else{handleEventWithGuard(receiveTime);} }//處理所有發(fā)生的事件 //EPOLLIN :表示對應(yīng)的文件描述符可以讀; //EPOLLOUT:表示對應(yīng)的文件描述符可以寫; //EPOLLPRI:表示對應(yīng)的文件描述符有緊急的數(shù)據(jù)可讀 //EPOLLERR:表示對應(yīng)的文件描述符發(fā)生錯誤; //EPOLLHUP:表示對應(yīng)的文件描述符被掛斷; //EPOLLET:表示對應(yīng)的文件描述符有事件發(fā)生; 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)) //POLLRDHUP是對端關(guān)閉連接事件,如shutdown等{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(); }?
總結(jié)
以上是生活随笔為你收集整理的muduo之channel的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: muduo之EPollPoller
- 下一篇: mutable关键字