-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathz_epoll.cpp
More file actions
94 lines (79 loc) · 2.62 KB
/
z_epoll.cpp
File metadata and controls
94 lines (79 loc) · 2.62 KB
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
#include "z_epoll.hpp"
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <sys/epoll.h>
#include "g.hpp"
#include "log.h"
#include "z_timer.hpp"
z_Epoll::z_Epoll() noexcept {
::signal(SIGPIPE, SIG_IGN);
ep_fd = epoll_create1(EPOLL_CLOEXEC);
}
z_Epoll::~z_Epoll() noexcept {
close(ep_fd);
}
void z_Epoll::run() noexcept {
constexpr int max_events = 128;
struct epoll_event events[max_events];
for (;;) {
flush_dirty_fds();
int timeout = g::timer_mgr.epoll_timeout();
int n_events = epoll_wait(ep_fd, events, max_events, timeout);
// update time wheel
// g::timer_mgr->update();
if (n_events < 0) [[unlikely]] {
if (errno == EINTR) continue;
log_error("epoll_wait(fd:%d, timeout:%d): (%d) %m", ep_fd, timeout, errno);
break;
}
// add ref
for (int i = 0; i < n_events; ++i) {
z_Fd *fd = (z_Fd *)events[i].data.ptr;
fd->ref();
}
for (int i = 0; i < n_events; ++i) {
z_Fd *fd = (z_Fd *)events[i].data.ptr;
uint32_t ev = events[i].events;
if (ev & (EPOLLIN | EPOLLHUP | EPOLLERR))
fd->on_readable();
if (ev & (EPOLLOUT | EPOLLHUP | EPOLLERR))
fd->on_writable();
// drop ref
fd->unref();
}
}
}
void z_Epoll::on_fd_dirty(z_Fd *fd) noexcept {
if (!fd->ep_node.linked())
dirty_fds.push_tail(fd);
}
void z_Epoll::on_fd_close(z_Fd *fd) noexcept {
fd->ep_node.unlink();
if (fd->ep_events != 0) {
epoll_ctl(ep_fd, EPOLL_CTL_DEL, fd->raw_fd, nullptr);
fd->unref(); // drop ref (own by epoll instance)
}
}
void z_Epoll::flush_dirty_fds() noexcept {
while (z_Fd *fd = dirty_fds.pop_head()) {
uint32_t want_events = 0;
if (!fd->read_wq.is_empty()) want_events |= EPOLLIN;
if (!fd->write_wq.is_empty()) want_events |= EPOLLOUT;
if (want_events != fd->ep_events) {
if (want_events == 0) {
epoll_ctl(ep_fd, EPOLL_CTL_DEL, fd->raw_fd, nullptr);
fd->unref(); // drop ref (own by epoll instance)
} else {
struct epoll_event ev{
.events = want_events | EPOLLET,
.data = { .ptr = fd },
};
int op = (fd->ep_events == 0) ? EPOLL_CTL_ADD : EPOLL_CTL_MOD;
epoll_ctl(ep_fd, op, fd->raw_fd, &ev);
if (op == EPOLL_CTL_ADD) fd->ref(); // add ref (own by epoll instance)
}
fd->ep_events = want_events;
}
}
}