概要
Poller基类定义了监听所有channel通道的监听者应该干哪些事情,是一个抽象类可以由Pollpoller和Epollpoller来继承实现重写里面的方法(IO复用基类,纯虚基类),它积极地监听着所有channel通道所发生的事情,并实时反应到channel,让channel update。是muduo库中多路事件分发器的核心IO复用模块(开启事件循环epollwait)
框架与细节
成员
protected:
//map的key:sockfd,channel的成员变量之一 value: sockfd所属的channel通道类型
using ChannelMap = std::unordered_map<int,Channel*>;//无序,hash表
ChannelMap channels_;
private:
EventLoop*ownerLoop_;//定义Poller所属的事件循环Eventloop
channels_
为哈希表,key 为 fd,val 为 channel,protected属性,让子类可以O(1)查找Poller中是否在监听某个channel。
private属性中,有一个EventLoop指针对象,代表Poller属于哪个EventLoop。
方法
//给所有io复用保留统一的接口
virtual Timestamp poll(int timeoutMs,ChannelList * activecChannels)=0;//启动epollwait
virtual void updateChannel(Channel *Channel) = 0;//epollctl
virtual void removeChannel(Channel *channel) = 0;
poll,updateChannel,removeChannel设为纯虚函数不做处理,等子类对相应的函数进行细节处理。
Poller的核心poll(),当外界调用了poll这个方法该方法的底层其实调用的是epoll_wait函数。我们知道在muduo库当中每一个fd都对应着一个Channel,哈西表channels_可以让我们通过fd找到与之对应的channel。将来事件监听器监听到该fd上有事件发生,就可以通过哈西表将具体发生了什么事件写入到channel当中。poll当中的ativateChannels他的类型是(vector<Channel*>),当外界调用poll方法之后可以通过activateChannels拿到监听结果,也就是那些文件描述符就绪了,并调用Channel当中的对应事件的回调函数。
源码
//Poller.h
#pragma once
#include <vector>
#include <unordered_map>
#include "noncopyable.h"
#include "Timestamp.h"
#include "Channel.h"
class Channel;
class EventLoop;
class Poller : noncopyable {
public:
using ChannelList = std::vector<Channel*>;
Poller(EventLoop* loop) : loop_(loop) {};
virtual ~Poller() = default;
virtual Timestamp poll(int timeoutMs, ChannelList* activeChannels) = 0;
virtual void updateChannel(Channel* channel) = 0;
virtual void removeChannel(Channel* channel) = 0;
bool hasChannel(Channel* channel) const;
static Poller* newDefaultPoller(EventLoop* loop);
protected:
using ChannelMap = std::unordered_map<int, Channel*>;
ChannelMap channels_;
private:
EventLoop* loop_;
};
//Poller.cc
#include "Poller.h"
bool Poller::hasChannel(Channel* channel) const {
auto it = channels_.find(channel->fd());
return it != channels_.end() && it->second == channel;
}