-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEPollPoller.cc
155 lines (128 loc) · 3.58 KB
/
EPollPoller.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include "EPollPoller.h"
#include "Logger.h"
#include "Channel.h"
#include <errno.h>
#include <unistd.h>
#include <strings.h>
// channel 未添加到 poller 中
const int kNew = -1;
// channel 已添加到 poller 中
const int kAdded = 1;
// channel 从 poller 中删除
const int kDeleted = 2;
EPollPoller::EPollPoller(EventLoop *loop)
: Poller(loop)
, epollfd_(::epoll_create1(EPOLL_CLOEXEC))
, events_(kInitEventListSize)
{
if (epollfd_ < 0)
{
LOG_FATAL("epoll_create error:%d \n", errno);
}
}
EPollPoller::~EPollPoller()
{
::close(epollfd_);
}
Timestamp EPollPoller::Poll(int timeout_ms, ChannelList *active_channels)
{
LOG_INFO("func=%s => fd total count:%lu \n", __FUNCTION__, channels_.size());
int num_events = ::epoll_wait(epollfd_, &*events_.begin(), static_cast<int>(events_.size()), timeout_ms);
int save_errno = errno;
Timestamp now(Timestamp::Now());
if (num_events > 0)
{
LOG_INFO("%d events happened \n", num_events);
FillActiveChannels(num_events, active_channels);
if (num_events == events_.size())
{
events_.resize(events_.size() * 2);
}
}
else if (num_events == 0)
{
LOG_DEBUG("%s timeout! \n", __FUNCTION__);
}
else
{
if (save_errno != EINTR)
{
errno = save_errno;
LOG_ERROR("EPollPoller::poll() err!");
}
}
return now;
}
// Channel Update/Remove => EventLoop UpdateChannel/RemoveChannel => Poller UpdateChannel/RemoveChannel
void EPollPoller::UpdateChannel(Channel *channel)
{
const int index = channel->index();
LOG_INFO("func=%s => fd=%d events=%d index=%d \n", __FUNCTION__, channel->fd(), channel->events(), index);
if (index == kNew || index == kDeleted)
{
if (index == kNew)
{
int fd = channel->fd();
channels_[fd] = channel;
}
channel->set_index(kAdded);
Update(EPOLL_CTL_ADD, channel);
}
else // channel 已经在 poller 上注册过了
{
int fd = channel->fd();
if (channel->IsNoneEvent())
{
Update(EPOLL_CTL_DEL, channel);
channel->set_index(kDeleted);
}
else
{
Update(EPOLL_CTL_MOD, channel);
}
}
}
// 从 poller 中删除 channel
void EPollPoller::RemoveChannel(Channel *channel)
{
int fd = channel->fd();
channels_.erase(fd);
LOG_INFO("func=%s => fd=%d\n", __FUNCTION__, fd);
int index = channel->index();
if (index == kAdded)
{
Update(EPOLL_CTL_DEL, channel);
}
channel->set_index(kNew);
}
void EPollPoller::FillActiveChannels(int num_events, ChannelList *active_channels) const
{
for (int i=0; i < num_events; ++i)
{
Channel *channel = static_cast<Channel*>(events_[i].data.ptr);
channel->set_revents(events_[i].events);
// EventLoop 拿到它的 poller 给它返回的所有发生事件的 channel 列表
active_channels->push_back(channel);
}
}
// 更新 channel 通道 epoll_ctl add/mod/del
void EPollPoller::Update(int operation, Channel *channel)
{
epoll_event event;
bzero(&event, sizeof event);
int fd = channel->fd();
event.events = channel->events();
event.data.fd = fd;
event.data.ptr = channel;
if (::epoll_ctl(epollfd_, operation, fd, &event) < 0)
{
if (operation == EPOLL_CTL_DEL)
{
LOG_ERROR("epoll_ctl del error:%d\n", errno);
}
else
{
LOG_FATAL("epoll_ctl add/mod error:%d\n", errno);
}
}
}