目录
Poller扮演角色:
TCP server里边儿非常重要的一个东西呢,就是event loop事件循环,一个事件循环对应一个线程,一个线程对应一个事件循环。
一个事件循环就是event loop里边对应了一个poller跟一堆的channel,现在来实现poller。
muduo的Eventloop在使用IO复用的时候,并没有直接指定epoll,muduo对象外提供IO复用的能力有2个,一个是poll,一个是epoll,是从抽象层面使用抽象基类Poller,到时候引用不同的派生类,调用同名覆盖方法,就可以非常方便的去扩展不同的IO复用能力。
Poller成员变量:
①: 存放所有Channel的容器,使用一个无序map;
②: 一个当前poller所在loop的指针。
Poller成员函数:
①:声明ChannelList链表容器,用于存放感兴趣的事件;
②:构造函数:
析构函数:要定义成虚函数,因为要做基类,后面EpollPoller将由它来派生
③:一系列的纯虚函数:
poll相当于启动了epoll_wait;updateChannel相当于启动了epoll_ctrl;removeChannel将fd所感兴趣的事件delete掉。
具体实现将在EpollPoller中描述。
④:判断传入参数的channel是否在当前poller的ChannelMap容器中
⑤:根据全局变量判断生成那种类型的IO复用poll或者epoll
Poller.h
#pragma once
#include "noncopyable.h"
#include "Timestamp.h"
#include <vector>
#include <unordered_map>
class Channel;//只用到指针类型
class EventLoop;//只用到指针类型
//muduo库中多路事件分发器的核心IO复用模块
class Poller : noncopyable
{
public:
using ChannelList = std::vector<Channel*>;
Poller(EventLoop *loop);
virtual ~Poller() = default;//虚析构函数
//给所有IO复用保留统一的接口 纯虚函数
virtual Timestamp poll(int timeoutMs, ChannelList *activeChannels) = 0;//相当于启动了epoll_wait
virtual void updateChannel(Channel *channel) = 0;//相当于启动了epoll_ctrl
virtual void removeChannel(Channel *channel) = 0;//fd所感兴趣的事件delete掉
//判断参数channel是否在当前Poller当中
bool hasChannel(Channel *channel) const;
//EventLoop可以通过该接口获取默认的IO复用的具体实现
static Poller* newDefaultPoller(EventLoop *loop);
protected:
//map的key:sockfd value:sockfd所属的channel通道类型
using ChannelMap = std::unordered_map<int, Channel*>;
ChannelMap channels_;
private:
EventLoop *ownerLoop_;//定义Poller所属的事件循环EventLoop
};
1. 因为muduo对外提供IO复用接口有两个一个是poll,一个是epoll;
2. 在eventloop中不可能直接使用poll或者epoll,也没有指定。
3. Poller类定义成抽象类,通过引用不同的派生类对象,可以调用同名覆盖方法,就可以非常方便的去扩展不同的IO复用能力。
可以通过newDefaultPoller(EventLoop *loop)函数实现IO复用类型
//公共源文件 #include "Poller.h" #include <stdlib.h> Poller* Poller::newDefaultPoller(EventLoop *loop) { if(::getenv("MUDUO_USE_POLL")) { return nullptr; //生成一个poll实例 }else{ return nullptr; //生成一个epoll实例 } }
通过环境变量控制,设置IO复用接口类型
poller成员变量包含了一个map里面存放多个channel。
protected:
//map的key:sockfd value:sockfd所属的channel通道类型
using ChannelMap = std::unordered_map<int, Channel*>;
ChannelMap channels_;
private:
EventLoop *ownerLoop_;//定义Poller所属的事件循环EventLoop
Poller.cc
#include "Poller.h"
#include "Channel.h"
Poller::Poller(EventLoop *loop)
: ownerLoop_(loop)
{
}
bool Poller::hasChannel(Channel *channel) const
{
auto it = channels_.find(channel->fd());
//保证这个channel在poller的map里面
return it != channels_.end() && it -> second == channel;
}