-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpoll.cpp
95 lines (82 loc) · 2.6 KB
/
poll.cpp
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
#include "poll.hpp"
namespace {
#if defined(__APPLE__) || defined(__FreeBSD__)
int ppoll(struct pollfd* fds, nfds_t nfds, const struct timespec* ts, const sigset_t* sigmask) {
int timeout = 0;
if (ts) {
timeout = ts->tv_sec;
timeout += ts->tv_nsec / 1000000;
}
// TODO: support sigmask
return poll(fds, nfds, timeout);
}
#endif
} // namespace
namespace NNet {
void TPoll::Poll() {
auto ts = GetTimeout();
if (static_cast<int>(InEvents_.size()) <= MaxFd_) {
InEvents_.resize(MaxFd_+1, std::make_tuple(THandlePair{}, -1));
}
for (const auto& ch : Changes_) {
int fd = ch.Fd;
auto& [ev, idx] = InEvents_[fd];
if (ch.Handle) {
if (idx == -1) {
idx = static_cast<int>(Fds_.size());
Fds_.emplace_back(pollfd{});
}
pollfd& pev = Fds_[idx];
pev.fd = fd;
if (ch.Type & TEvent::READ) {
pev.events |= POLLIN;
ev.Read = ch.Handle;
}
if (ch.Type & TEvent::WRITE) {
pev.events |= POLLOUT;
ev.Write = ch.Handle;
}
} else if (idx != -1) {
if (ch.Type & TEvent::READ) {
Fds_[idx].events &= ~POLLIN;
ev.Read = {};
}
if (ch.Type & TEvent::WRITE) {
Fds_[idx].events &= ~POLLOUT;
ev.Write = {};
}
if (Fds_[idx].events == 0) {
std::swap(Fds_[idx], Fds_.back());
std::get<1>(InEvents_[Fds_[idx].fd]) = idx;
Fds_.back().events = 0;
idx = -1;
}
}
}
while (!Fds_.empty() && !Fds_.back().events) {
Fds_.pop_back();
}
Reset();
if (ppoll(&Fds_[0], Fds_.size(), &ts, nullptr) < 0) {
throw std::system_error(errno, std::generic_category(), "poll");
}
for (auto& pev : Fds_) {
auto [ev, _] = InEvents_[pev.fd];
if (pev.revents & POLLIN) {
ReadyEvents_.emplace_back(TEvent{pev.fd, TEvent::READ, ev.Read}); ev.Read = {};
}
if (pev.revents & POLLOUT) {
ReadyEvents_.emplace_back(TEvent{pev.fd, TEvent::WRITE, ev.Write}); ev.Write = {};
}
if (pev.revents & POLLHUP) {
if (ev.Read) {
ReadyEvents_.emplace_back(TEvent{pev.fd, TEvent::READ, ev.Read});
}
if (ev.Write) {
ReadyEvents_.emplace_back(TEvent{pev.fd, TEvent::WRITE, ev.Write});
}
}
}
ProcessTimers();
}
} // namespace NNet