muduo网络库使用 muiltiple reactors + threadpool(one loop per thread + threadpool) 模型。
- one loop per thread :每个线程最多只能有一个EventLoop对象,如果已经创建,则终止程序(LOG_FATAL)
- EventLoop构造函数会记住本对象所属线程(threadId_)
- 创建了EventLoop对象的线程称为IO线程,其功能是运行事件循环(EventLoop::loop)
//EventLoop.h/.cc
//不能跨线程调用
bool looping_;
void EventLoop::loop()
{
assert(!looping_); //断言当前没有在循环
assertInLoopThread(); //断言在LoopThread中
looping_ = true;
}
void assertInLoopThread()
{
if (!isInLoopThread())//判断当前线程是否时创建当前EL对象的线程
{
abortNotInLoopThread();//终止程序
}
}
bool isInLoopThread() const { return threadId_ == CurrentThread::tid(); }
const pid_t threadId_; //当前对象所属线程ID
std::unique_ptr<Poller> poller_;
ChannelList activeChannels_; //Poller返回的活动通道
Channel* currentActiveChannel_; //当前正在处理的活动通道
void updateChannel(Channel* channel); //在Poller中添加(注册)或者更新通道
//channel.h/.cc
class Channel : noncopyable{
public:
void enableReading() { events_ |= kReadEvent; update(); }
void disableReading() { events_ &= ~kReadEvent; update(); }
void enableWriting() { events_ |= kWriteEvent; update(); }
void disableWriting() { events_ &= ~kWriteEvent; update(); }
private:
EventLoop* loop_; //所属EvenLoop对象
const int fd_; //文件描述符,但不控制该fd
int events_; //关注的事件
int revents_; //实际返回的事件
int index_; //在poll事件数组中的序号
};
- 一个EventLoop对应一个Poller
- update()会调用EventLoop::updateChannel(), EventLoop对象持有Poller对象,调用Poller::updateChannel, 将事件注册到poll中
//Poller类
class Poller : noncopyable
{
public:
typedef std::vector<Channel*> ChannelList;
Poller(EventLoop* loop);
virtual ~Poller();
/// Polls the I/O events.
/// Must be called in the loop thread.
virtual Timestamp poll(int timeoutMs, ChannelList* activeChannels) = 0;
/// Changes the interested I/O events.
/// Must be called in the loop thread.
virtual void updateChannel(Channel* channel) = 0;
virtual void removeChannel(Channel* channel) = 0;
...
protected:
typedef std::map<int, Channel*> ChannelMap; //key是文件描述符
ChannelMap channels_;
private:
EventLoop* ownerLoop_;
};
Poller类中的纯虚函数在其子类PollPoller中实现
//PollPoller类
class PollPoller : public Poller
{
public:
Timestamp poll(int timeoutMs, ChannelList* activeChannels) override;
void updateChannel(Channel* channel) override;
void removeChannel(Channel* channel) override;
private:
void fillActiveChannels(int numEvents,
ChannelList* activeChannels) const;
typedef std::vector<struct pollfd> PollFdList;
PollFdList pollfds_;
};
Timestamp PollPoller::poll(int timeoutMs, ChannelList* activeChannels)
{
int numEvents = ::poll(&*pollfds_.begin(), pollfds_.size(), timeoutMs);
Timestamp now(Timestamp::now());
if (numEvents > 0)
{
fillActiveChannels(numEvents, activeChannels);
}
...
return now;
}
void PollPoller::updateChannel(Channel* channel)
{
Poller::assertInLoopThread();
if (channel->index() < 0) //index_初始话为-1
{
// a new one, add to pollfds_
assert(channels_.find(channel->fd()) == channels_.end());
struct pollfd pfd;
pfd.fd = channel->fd();
pfd.events = static_cast<short>(channel->events());
pfd.revents = 0;
pollfds_.push_back(pfd);
int idx = static_cast<int>(pollfds_.size())-1;
channel->set_index(idx);
channels_[pfd.fd] = channel;
}
else
{
// update existing one
...
}
}