来看Poller的成员函数定义:
可以看到Poller有几个纯虚函数接口,是一个抽象类。为什么要设计成抽象类呢?
muduo提供了两个IO复用能力:poll和epoll,但并没有指定要用epoll,Poller的抽象就可以很容易的扩展不同的IO复用能力,通过Poller提供的newDefaultPoller
接口,就可以给用户构造一个默认的Poller。
muduo通过环境变量来控制用poll还是epoll,默认使用epoll。
需要注意,newDefaultPoller尽量不要在Poller中定义的 。
因为在继承结构中,Poller是基类,PollPoller和EPollPoller是派生类,只能是派生类引用基类,基类不能引用派生类。 虽然语法上没什么错误,但这样不合理。
重写Poller.h:
#pragma once
#include "noncopyable.h"
#include "Timestamp.h"
#include
#include
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* activeChannel) = 0;
virtual void updateChannel(Channel* channel) = 0;
virtual void removeChannel(Channel* channel) = 0;
bool hasChannel(Channel* channel) const;
//EventLoop可以通过该接口获取默认的IO复用的具体实现
static Poller* newDefaultPoller(EventLoop* loop);
protected:
//map的key表示sockfd value表示sockefd所属的channel通道类型
using ChannelMap = std::unordered_map<int,Channel*>;
ChannelMap channels_;
private:
EventLoop *ownerLoop_;
};
重写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());
return it != channels_.end() && it->second == channel;
}