@@ -113,73 +113,103 @@ int Sock::SetSockOpt(int level, int opt_name, const void* opt_val, socklen_t opt
113113
114114bool Sock::Wait (std::chrono::milliseconds timeout, Event requested, Event* occurred) const
115115{
116- #ifdef USE_POLL
117- pollfd fd;
118- fd.fd = m_socket;
119- fd.events = 0 ;
120- if (requested & RECV) {
121- fd.events |= POLLIN;
122- }
123- if (requested & SEND) {
124- fd.events |= POLLOUT;
125- }
116+ // We need a `shared_ptr` owning `this` for `WaitMany()`, but don't want
117+ // `this` to be destroyed when the `shared_ptr` goes out of scope at the
118+ // end of this function. Create it with a custom noop deleter.
119+ std::shared_ptr<const Sock> shared{this , [](const Sock*) {}};
120+
121+ EventsPerSock events_per_sock{std::make_pair (shared, Events{requested})};
126122
127- if (poll (&fd, 1 , count_milliseconds (timeout)) == SOCKET_ERROR ) {
123+ if (! WaitMany (timeout, events_per_sock) ) {
128124 return false ;
129125 }
130126
131127 if (occurred != nullptr ) {
132- *occurred = 0 ;
133- if (fd.revents & POLLIN) {
134- *occurred |= RECV;
135- }
136- if (fd.revents & POLLOUT) {
137- *occurred |= SEND;
128+ *occurred = events_per_sock.begin ()->second .occurred ;
129+ }
130+
131+ return true ;
132+ }
133+
134+ bool Sock::WaitMany (std::chrono::milliseconds timeout, EventsPerSock& events_per_sock) const
135+ {
136+ #ifdef USE_POLL
137+ std::vector<pollfd> pfds;
138+ for (const auto & [sock, events] : events_per_sock) {
139+ pfds.emplace_back ();
140+ auto & pfd = pfds.back ();
141+ pfd.fd = sock->m_socket ;
142+ if (events.requested & RECV) {
143+ pfd.events |= POLLIN;
138144 }
139- if (fd. revents & (POLLERR | POLLHUP) ) {
140- *occurred |= ERR ;
145+ if (events. requested & SEND ) {
146+ pfd. events |= POLLOUT ;
141147 }
142148 }
143149
144- return true ;
145- #else
146- if (!IsSelectableSocket (m_socket)) {
150+ if (poll (pfds.data (), pfds.size (), count_milliseconds (timeout)) == SOCKET_ERROR) {
147151 return false ;
148152 }
149153
150- fd_set fdset_recv;
151- fd_set fdset_send;
152- fd_set fdset_err;
153- FD_ZERO (&fdset_recv);
154- FD_ZERO (&fdset_send);
155- FD_ZERO (&fdset_err);
156-
157- if (requested & RECV) {
158- FD_SET (m_socket, &fdset_recv);
154+ assert (pfds.size () == events_per_sock.size ());
155+ size_t i{0 };
156+ for (auto & [sock, events] : events_per_sock) {
157+ assert (sock->m_socket == static_cast <SOCKET>(pfds[i].fd ));
158+ events.occurred = 0 ;
159+ if (pfds[i].revents & POLLIN) {
160+ events.occurred |= RECV;
161+ }
162+ if (pfds[i].revents & POLLOUT) {
163+ events.occurred |= SEND;
164+ }
165+ if (pfds[i].revents & (POLLERR | POLLHUP)) {
166+ events.occurred |= ERR;
167+ }
168+ ++i;
159169 }
160170
161- if (requested & SEND) {
162- FD_SET (m_socket, &fdset_send);
171+ return true ;
172+ #else
173+ fd_set recv;
174+ fd_set send;
175+ fd_set err;
176+ FD_ZERO (&recv);
177+ FD_ZERO (&send);
178+ FD_ZERO (&err);
179+ SOCKET socket_max{0 };
180+
181+ for (const auto & [sock, events] : events_per_sock) {
182+ const auto & s = sock->m_socket ;
183+ if (!IsSelectableSocket (s)) {
184+ return false ;
185+ }
186+ if (events.requested & RECV) {
187+ FD_SET (s, &recv);
188+ }
189+ if (events.requested & SEND) {
190+ FD_SET (s, &send);
191+ }
192+ FD_SET (s, &err);
193+ socket_max = std::max (socket_max, s);
163194 }
164195
165- FD_SET (m_socket, &fdset_err);
166-
167- timeval timeout_struct = MillisToTimeval (timeout);
196+ timeval tv = MillisToTimeval (timeout);
168197
169- if (select (m_socket + 1 , &fdset_recv , &fdset_send , &fdset_err , &timeout_struct ) == SOCKET_ERROR) {
198+ if (select (socket_max + 1 , &recv , &send , &err , &tv ) == SOCKET_ERROR) {
170199 return false ;
171200 }
172201
173- if (occurred != nullptr ) {
174- *occurred = 0 ;
175- if (FD_ISSET (m_socket, &fdset_recv)) {
176- *occurred |= RECV;
202+ for (auto & [sock, events] : events_per_sock) {
203+ const auto & s = sock->m_socket ;
204+ events.occurred = 0 ;
205+ if (FD_ISSET (s, &recv)) {
206+ events.occurred |= RECV;
177207 }
178- if (FD_ISSET (m_socket , &fdset_send )) {
179- * occurred |= SEND;
208+ if (FD_ISSET (s , &send )) {
209+ events. occurred |= SEND;
180210 }
181- if (FD_ISSET (m_socket , &fdset_err )) {
182- * occurred |= ERR;
211+ if (FD_ISSET (s , &err )) {
212+ events. occurred |= ERR;
183213 }
184214 }
185215
0 commit comments