]>
Commit | Line | Data |
---|---|---|
870a0fe4 AT |
1 | #ifdef HAVE_CONFIG_H |
2 | #include "config.h" | |
3 | #endif | |
cfa2996a BH |
4 | #include "mplexer.hh" |
5 | #include "sstuff.hh" | |
6 | #include <iostream> | |
7 | #include <poll.h> | |
2ee30ed7 | 8 | #include <unordered_map> |
cfa2996a | 9 | #include "misc.hh" |
10f4eea8 | 10 | #include "namespaces.hh" |
cfa2996a | 11 | |
7c58a81f | 12 | FDMultiplexer* FDMultiplexer::getMultiplexerSilent(unsigned int maxEventsHint) |
4226cfd0 | 13 | { |
14 | FDMultiplexer* ret = nullptr; | |
e16e673d | 15 | for (const auto& i : FDMultiplexer::getMultiplexerMap()) { |
4226cfd0 | 16 | try { |
7c58a81f | 17 | ret = i.second(std::min(maxEventsHint, FDMultiplexer::s_maxevents)); |
4226cfd0 | 18 | return ret; |
19 | } | |
e16e673d | 20 | catch (const FDMultiplexerException& fe) { |
4226cfd0 | 21 | } |
e16e673d | 22 | catch (...) { |
4226cfd0 | 23 | } |
24 | } | |
25 | return ret; | |
26 | } | |
27 | ||
926444e2 | 28 | class PollFDMultiplexer : public FDMultiplexer |
29 | { | |
30 | public: | |
d73de874 | 31 | PollFDMultiplexer(unsigned int /* maxEventsHint */) |
926444e2 | 32 | {} |
926444e2 | 33 | |
e16e673d RG |
34 | int run(struct timeval* tv, int timeout = 500) override; |
35 | void getAvailableFDs(std::vector<int>& fds, int timeout) override; | |
926444e2 | 36 | |
e16e673d RG |
37 | void addFD(int fd, FDMultiplexer::EventKind) override; |
38 | void removeFD(int fd, FDMultiplexer::EventKind) override; | |
5bdbb83d RG |
39 | |
40 | string getName() const override | |
926444e2 | 41 | { |
42 | return "poll"; | |
43 | } | |
e16e673d | 44 | |
926444e2 | 45 | private: |
5efe08a2 | 46 | std::unordered_map<int, struct pollfd> d_pollfds; |
5bdbb83d | 47 | vector<struct pollfd> preparePollFD() const; |
926444e2 | 48 | }; |
cfa2996a | 49 | |
7c58a81f | 50 | static FDMultiplexer* make(unsigned int maxEventsHint) |
cfa2996a | 51 | { |
7c58a81f | 52 | return new PollFDMultiplexer(maxEventsHint); |
cfa2996a BH |
53 | } |
54 | ||
55 | static struct RegisterOurselves | |
56 | { | |
e16e673d RG |
57 | RegisterOurselves() |
58 | { | |
d90323cc | 59 | FDMultiplexer::getMultiplexerMap().emplace(2, &make); |
cfa2996a BH |
60 | } |
61 | } doIt; | |
62 | ||
5efe08a2 RG |
63 | static int convertEventKind(FDMultiplexer::EventKind kind) |
64 | { | |
65 | switch (kind) { | |
66 | case FDMultiplexer::EventKind::Read: | |
67 | return POLLIN; | |
68 | case FDMultiplexer::EventKind::Write: | |
69 | return POLLOUT; | |
70 | case FDMultiplexer::EventKind::Both: | |
71 | return POLLIN | POLLOUT; | |
72 | } | |
73 | throw std::runtime_error("Unhandled event kind in the ports multiplexer"); | |
74 | } | |
75 | ||
e16e673d | 76 | void PollFDMultiplexer::addFD(int fd, FDMultiplexer::EventKind kind) |
cfa2996a | 77 | { |
5efe08a2 RG |
78 | if (d_pollfds.count(fd) == 0) { |
79 | auto& pollfd = d_pollfds[fd]; | |
80 | pollfd.fd = fd; | |
81 | pollfd.events = 0; | |
82 | } | |
83 | auto& pollfd = d_pollfds.at(fd); | |
84 | pollfd.events |= convertEventKind(kind); | |
cfa2996a BH |
85 | } |
86 | ||
e16e673d | 87 | void PollFDMultiplexer::removeFD(int fd, FDMultiplexer::EventKind) |
cfa2996a | 88 | { |
5efe08a2 | 89 | d_pollfds.erase(fd); |
cfa2996a BH |
90 | } |
91 | ||
5bdbb83d | 92 | vector<struct pollfd> PollFDMultiplexer::preparePollFD() const |
cfa2996a | 93 | { |
e16e673d | 94 | std::vector<struct pollfd> result; |
5efe08a2 RG |
95 | result.reserve(d_pollfds.size()); |
96 | for (const auto& entry : d_pollfds) { | |
e16e673d | 97 | result.push_back(entry.second); |
cfa2996a BH |
98 | } |
99 | ||
e16e673d | 100 | return result; |
5bdbb83d RG |
101 | } |
102 | ||
103 | void PollFDMultiplexer::getAvailableFDs(std::vector<int>& fds, int timeout) | |
104 | { | |
105 | auto pollfds = preparePollFD(); | |
e16e673d RG |
106 | if (pollfds.empty()) { |
107 | return; | |
108 | } | |
109 | ||
5bdbb83d RG |
110 | int ret = poll(&pollfds[0], pollfds.size(), timeout); |
111 | ||
e16e673d | 112 | if (ret < 0 && errno != EINTR) { |
5bdbb83d | 113 | throw FDMultiplexerException("poll returned error: " + stringerror()); |
e16e673d | 114 | } |
5bdbb83d | 115 | |
e16e673d RG |
116 | for (const auto& pollfd : pollfds) { |
117 | if (pollfd.revents & POLLIN || pollfd.revents & POLLOUT || pollfd.revents & POLLERR || pollfd.revents & POLLHUP) { | |
5bdbb83d RG |
118 | fds.push_back(pollfd.fd); |
119 | } | |
120 | } | |
121 | } | |
122 | ||
123 | int PollFDMultiplexer::run(struct timeval* now, int timeout) | |
124 | { | |
e16e673d | 125 | if (d_inrun) { |
5bdbb83d RG |
126 | throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n"); |
127 | } | |
128 | ||
129 | auto pollfds = preparePollFD(); | |
e16e673d RG |
130 | if (pollfds.empty()) { |
131 | gettimeofday(now, nullptr); // MANDATORY! | |
132 | return 0; | |
133 | } | |
5bdbb83d | 134 | |
e16e673d RG |
135 | int ret = poll(&pollfds[0], pollfds.size(), timeout); |
136 | gettimeofday(now, nullptr); // MANDATORY! | |
137 | ||
138 | if (ret < 0 && errno != EINTR) { | |
139 | throw FDMultiplexerException("poll returned error: " + stringerror()); | |
140 | } | |
141 | ||
142 | d_inrun = true; | |
c7a9f1b4 | 143 | int count = 0; |
e16e673d | 144 | for (const auto& pollfd : pollfds) { |
e16e673d RG |
145 | if (pollfd.revents & POLLIN || pollfd.revents & POLLERR || pollfd.revents & POLLHUP) { |
146 | const auto& iter = d_readCallbacks.find(pollfd.fd); | |
147 | if (iter != d_readCallbacks.end()) { | |
148 | iter->d_callback(iter->d_fd, iter->d_parameter); | |
c7a9f1b4 | 149 | count++; |
cfa2996a BH |
150 | } |
151 | } | |
e16e673d RG |
152 | |
153 | if (pollfd.revents & POLLOUT || pollfd.revents & POLLERR) { | |
154 | const auto& iter = d_writeCallbacks.find(pollfd.fd); | |
155 | if (iter != d_writeCallbacks.end()) { | |
156 | iter->d_callback(iter->d_fd, iter->d_parameter); | |
c7a9f1b4 | 157 | count++; |
cfa2996a BH |
158 | } |
159 | } | |
160 | } | |
e16e673d RG |
161 | |
162 | d_inrun = false; | |
c7a9f1b4 | 163 | return count; |
cfa2996a BH |
164 | } |
165 | ||
166 | #if 0 | |
167 | ||
168 | void acceptData(int fd, boost::any& parameter) | |
169 | { | |
170 | cout<<"Have data on fd "<<fd<<endl; | |
171 | Socket* sock=boost::any_cast<Socket*>(parameter); | |
172 | string packet; | |
173 | IPEndpoint rem; | |
174 | sock->recvFrom(packet, rem); | |
175 | cout<<"Received "<<packet.size()<<" bytes!\n"; | |
176 | } | |
177 | ||
178 | ||
179 | int main() | |
180 | { | |
a5794017 | 181 | Socket s(AF_INET, SOCK_DGRAM); |
e16e673d | 182 | |
cfa2996a BH |
183 | IPEndpoint loc("0.0.0.0", 2000); |
184 | s.bind(loc); | |
185 | ||
186 | PollFDMultiplexer sfm; | |
187 | ||
188 | sfm.addReadFD(s.getHandle(), &acceptData, &s); | |
189 | ||
190 | for(int n=0; n < 100 ; ++n) { | |
191 | sfm.run(); | |
192 | } | |
193 | sfm.removeReadFD(s.getHandle()); | |
194 | sfm.removeReadFD(s.getHandle()); | |
195 | } | |
196 | #endif |