LIPH's C++ Codes
poll.h
Go to the documentation of this file.
1#ifndef LIPH_IO_POLL_H_
2#define LIPH_IO_POLL_H_
3
4#include "liph/macros.h"
5
6#ifdef OS_UNIX
7
8#include <poll.h>
9
10#include <cstdint>
11#include <map>
12#include <vector>
13
14#include "liph/io/descriptor.h"
15
16struct epoll_event;
17
18namespace liph::io {
19
20enum class event_type { read, write, read_write };
21
22struct poll_event {
23 int fd;
24 event_type type;
25 void *ptr;
26};
27
28class poll_base {
29public:
30 poll_base() {}
31 virtual ~poll_base() {}
32 virtual bool add(descriptor fd, event_type type, void *ptr) = 0;
33 virtual bool del(descriptor fd) = 0;
34 // -1 for error, 0 for timeout, positive for nums of ready descriptor
35 virtual int wait(std::vector<poll_event>& events, int64_t timeout_us) = 0;
36};
37
38class poll : public poll_base {
39public:
40 poll() {}
41 ~poll() {}
42
43 bool add(descriptor fd, event_type type, void *ptr) override {
44 if (fdmap_.find(fd) != fdmap_.end()) {
45 return false;
46 }
47 fdmap_[fd.fd()] = std::make_pair(type, ptr);
48 update_ = true;
49 return true;
50 }
51
52 bool del(descriptor fd) override {
53 if (fdmap_.find(fd) == fdmap_.end()) {
54 return false;
55 }
56 fdmap_.erase(fd.fd());
57 update_ = true;
58 return true;
59 }
60
61 int wait(std::vector<poll_event>& events, int64_t timeout_us) override {
62 update();
63 int r = ::poll(fdset_.data(), fdset_.size(), timeout_us < 0 ? -1 : timeout_us / 1000);
64 if (r <= 0) {
65 return r;
66 }
67 events.resize(r);
68 int i = 0;
69 for (auto it = fdset_.begin(); i < r && it != fdset_.end(); ++it) {
70 if (it->revents & POLLIN && it->revents & POLLOUT) {
71 events[i].fd = it->fd;
72 events[i].type = event_type::read_write;
73 events[i].ptr = fdmap_[it->fd].second;
74 i++;
75 }
76 }
77 if (i != r) {
78 events.clear();
79 return false;
80 }
81 return r;
82 }
83
84private:
85 void update() {
86 if (update_) {
87 fdset_.resize(fdmap_.size());
88 int i = 0;
89 for (const auto& pair : fdmap_) {
90 fdset_[i].fd = pair.first;
91 switch (pair.second.first) {
92 case event_type::read:
93 fdset_[i].events = POLLIN;
94 break;
95 case event_type::write:
96 fdset_[i].events = POLLOUT;
97 break;
98 default:
99 fdset_[i].events = POLLIN | POLLOUT;
100 }
101 fdset_[i].revents = 0;
102 i++;
103 }
104 update_ = false;
105 }
106 }
107
108private:
109 std::map<int, std::pair<event_type, void *>> fdmap_;
110 std::vector<struct ::pollfd> fdset_;
111 bool update_{false};
112};
113
114class Poll {
115public:
116 Poll();
117
118 ~Poll();
119
120 operator bool() const { return epfd_ != -1; }
121
122 bool add(int fd, void *ptr);
123
124 bool del(int fd);
125
126 bool wait(std::vector<void *>& ptrs);
127
128 static const int maxevents;
129
130 // private:
131 int epfd_;
132 struct epoll_event *evlist_;
133};
134
135} // namespace liph::io
136
137namespace liph {
138
139class poller {
140public:
141 enum event { none, read, write };
142
143public:
144 // nfds: fdarray element size
145 // timeout = -1, wait forever; timeout = 0, do not wait; timeout > 0, wait timeout milliseconds
146 // return 0 if timeout, -1 if error and number of ready file descriptors otherwise
147 static int poll(struct pollfd fdarray[], nfds_t nfds, int timeout) { return ::poll(fdarray, nfds, timeout); }
148
149private:
150};
151
152} // namespace liph
153
154#endif
155
156#endif // LIPH_IO_POLL_H_
Definition: descriptor.h:6
Definition: algorithm.h:10