Poller是抽象类 为什么muduo库要抽象一层Poller? 因为在eventloop里面,在使用I/O复用的时候,并没有直接指定epoll,因为muduo库对外提供I/O复用的能力有2个:1个是poll,1个是epoll,在eventloop里面,不可能直接去使用poll或者epoll。 是从抽象层面直接使用抽象类poller,到时候引用不同的派生类对象,调用同名覆盖方法,就可以非常方便地去扩展不同的I/O复用能力,多路分发器。 poller监听的就是eventloop保存的那些channel protected的成员变量就是让派生类可以访问到,private的成员变量派生类不能访问到。
Poller.h
#pragma once
#include "noncopyable.h"
#include "Timestamp.h"
#include <vector>
#include <unordered_map>
class Channel;
class EventLoop;
class Poller : noncopyable
{
public:
using ChannelList = std::vector<Channel*>;
Poller(EventLoop *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 *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;
}
为什么不把 newDefaultPoller写在Poller.cc?
如果真的把newDefaultPoller写在Poller.cc里面,从语法上来说,没有错误。 但是这个函数是要生成一个具体的I/O复用对象,并返回一个基类的指针。 所以就得用下面这2个头文件,才能去生成一个具体的实例对象并返回回去,这样不合理,因为继承结构中,poller是基类,只能派生类引用基类,基类不能引用派生类 那这个newDefaultPoller实现在哪呢?
muduo默认使用epoll 获取环境变量
DefaultPoller.cc
#include "Poller.h"
#include "EPollPoller.h"
#include <stdlib.h>
Poller* Poller::newDefaultPoller(EventLoop *loop)
{
if (::getenv("MUDUO_USE_POLL"))
{
return nullptr;
}
else
{
return new EPollPoller(loop);
}
}
|