Channel我们前面说过了它是一个事件处理器,看看它的对象
boost::weak_ptr 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)
{
}
我们前面知道Acceptor和TcpConnection都用了Channel的setReadCallback,而这个函数呢就是相当于设置了Channel中的ReadBack回调函数,而这个ReadBack函数的作用是在Epoll一旦触发了就绪事件的回调函数
void setReadCallback(const ReadEventCallback& cb)
{ readCallback_ = cb; }
//调用底下的处理事件
void Channel::handleEvent(Timestamp receiveTime)
{
boost::shared_ptr 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 << "Channel::handle_event() POLLHUP";
}
if (closeCallback_) closeCallback_();
}
if (revents_ & POLLNVAL)
{
LOG_WARN << "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;
}
void enableReading() { events_ |= kReadEvent; update(); }
void Channel::update()
{
addedToLoop_ = true;
loop_->updateChannel(this);
}
我们可以看到它调用了Eventloop中的updateChannel(),虽然我们还没说到Eventloop,但是我们先走进去继续往下看吧,等后面说完Eventloop再来把之前的坑给补上:
//添加事件
void EventLoop::updateChannel(Channel* channel)
{
assert(channel->ownerLoop() == this);
assertInLoopThread();
poller_->updateChannel(channel);
}
我们看到它又调用了一个poller**底下的updateChannel()(我想吐槽为什么封装那么多),我们现在这里先不细说**poller,因为它是一个抽象类,它会供我们去选择epoll或者poll,我后面并没有分析poll的部分,而只是分析了epoll,直接进入epoll看就好咯:
//注册事件
void EPollPoller::updateChannel(Channel* channel)
{
Poller::assertInLoopThread();
LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events();
const int index = channel->index();
if (index == kNew || index == kDeleted)
{
// a new one, add with EPOLL_CTL_ADD
int fd = channel->fd();
if (index == kNew)
{
assert(channels_.find(fd) == channels_.end());
channels_[fd] = channel;
}
else // index == kDeleted
{
assert(channels_.find(fd) != channels_.end());
assert(channels_[fd] == channel);
}
channel->set_index(kAdded);
update(EPOLL_CTL_ADD, channel);
}
else
{
// 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);
channel->set_index(kDeleted);
}
else
{
update(EPOLL_CTL_MOD, channel);
}
}
}
//注册删除事件核心
void EPollPoller::update(int operation, Channel* channel)
{
struct epoll_event event;
bzero(&event, sizeof event);
event.events = channel->events();
event.data.ptr = channel;
int fd = channel->fd();
//核心
if (::epoll_ctl(epollfd_, operation, fd, &event) < 0)
{
if (operation == EPOLL_CTL_DEL)
{
LOG_SYSERR << "epoll_ctl op=" << operation << " fd=" << fd;
}
else
{
LOG_SYSFATAL << "epoll_ctl op=" << operation << " fd=" << fd;
}
}
}
bool looping_; /* atomic */
bool quit_; /* atomic and shared between threads, okay on x86, I guess. */
bool eventHandling_; /* atomic */
bool callingPendingFunctors_; /* atomic */
int64_t iteration_;
const pid_t threadId_;
Timestamp pollReturnTime_;//时间戳
boost::scoped_ptr poller_;//底层的poll或者epoll
boost::scoped_ptr timerQueue_;//时间队列
typedef std::vector ChannelList;
ChannelList activeChannels_;//就绪事件
Channel* currentActiveChannel_;//当前就绪事件
EventLoop::EventLoop()
: looping_(false),
quit_(false),
eventHandling_(false),
callingPendingFunctors_(false),
iteration_(0),
threadId_(CurrentThread::tid()),
poller_(Poller::newDefaultPoller(this)),//选择poll或者epoll
timerQueue_(new TimerQueue(this)),//epoll_wait的时间列表
wakeupFd_(createEventfd()),//线程间通信需要的fd
wakeupChannel_(new Channel(this, wakeupFd_)),
currentActiveChannel_(NULL)
{
//...貌似应该和ioloop有关,跟主线程和线程之间的响应有关
wakeupChannel_->setReadCallback(
boost::bind(&EventLoop::handleRead, this));
// we are always reading the wakeupfd
wakeupChannel_->enableReading();
}
Poller* Poller::newDefaultPoller(EventLoop* loop)
{
if (::getenv("MUDUO_USE_POLL"))
{
return new PollPoller(loop);
}
else
{
return new EPollPoller(loop);
}
}
EPollPoller::EPollPoller(EventLoop* loop)
: Poller(loop),
//构造一个epoll
epollfd_(::epoll_create1(EPOLL_CLOEXEC)),
events_(kInitEventListSize)
我们能看到它调用了epoll_create,创建一个epoll事件队列
我们再转回Eventloop中:
我们要知道Eventloop最重要的一个函数就是loop(),我们应该分析的是这个函数:
void EventLoop::loop()
{
assert(!looping_);
assertInLoopThread();
looping_ = true;
quit_ = false; // FIXME: what if someone calls quit() before loop() ?
LOG_TRACE << "EventLoop " << this << " start looping";
//quit这个其实和线程有点关系,当然你要了解更多详细的请去看陈硕的书= =!!
while (!quit_)
{
//前面其实我们有看到这就是一个就是就绪事件列表哦
activeChannels_.clear();//删除事件列表所有元素
pollReturnTime_ = poller_->poll(kPollTimeMs, &activeChannels_);//!!!最重要的函数(我们可以看到这里它把activeChannels_传了进去)
++iteration_;
if (Logger::logLevel() <= Logger::TRACE)
{
printActiveChannels();
}
// TODO sort channel by priority
eventHandling_ = true;
for (ChannelList::iterator it = activeChannels_.begin();
//把传进去的activeChannels_的就绪事件提取出来
it != activeChannels_.end(); ++it)
{
currentActiveChannel_ = *it;
//根据就绪事件处理事件
currentActiveChannel_->handleEvent(pollReturnTime_);
}
currentActiveChannel_ = NULL;
eventHandling_ = false;
doPendingFunctors();
}
LOG_TRACE << "EventLoop " << this << " stop looping";
looping_ = false;
}
Timestamp EPollPoller::poll(int timeoutMs, ChannelList* activeChannels)
{
//我们看到这里调用了epoll_wait,这里当然就是监听就绪事件的文件描述符了
int numEvents = ::epoll_wait(epollfd_,
&*events_.begin(),
static_cast(events_.size()),
timeoutMs);
int savedErrno = errno;
Timestamp now(Timestamp::now());
if (numEvents > 0)
{
LOG_TRACE << numEvents << " events happended";
//将就绪事件放入就绪队列拉到Eventloop中统一处理
fillActiveChannels(numEvents, activeChannels);
if (implicit_cast(numEvents) == events_.size())
{
events_.resize(events_.size()*2);
}
}
else if (numEvents == 0)
{
LOG_TRACE << " nothing happended";
}
else
{
// error happens, log uncommon ones
if (savedErrno != EINTR)
{
errno = savedErrno;
LOG_SYSERR << "EPollPoller::poll()";
}
}
return now;
}
//将就绪事件放到activeChannels中
void EPollPoller::fillActiveChannels(int numEvents,
ChannelList* activeChannels) const
{
assert(implicit_cast(numEvents) <= events_.size());
for (int i = 0; i < numEvents; ++i)
{
//将就绪事件取出来放入到就绪事件列表中
Channel* channel = static_cast(events_[i].data.ptr);
#ifndef NDEBUG
int fd = channel->fd();
ChannelMap::const_iterator it = channels_.find(fd);
assert(it != channels_.end());
assert(it->second == channel);
#endif
channel->set_revents(events_[i].events);
activeChannels->push_back(channel);
}
}