Refactor linux driver to use poll instead of select
This commit is contained in:
@@ -325,25 +325,47 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void handle_socket_input_output(int mstimeout) {
|
void handle_socket_input_output(int mstimeout) {
|
||||||
fd_set rfds, wfds, efds;
|
// Construct the pollfd vector.
|
||||||
int nbytes; const char *bytes;
|
std::vector<struct pollfd> pollvec;
|
||||||
int nfds = calc_select_sets(rfds, wfds, efds);
|
pollvec.resize(listen_sockets_.size() + chans_.size() + 1);
|
||||||
struct timeval timeout;
|
int index = 0;
|
||||||
timeout.tv_sec = mstimeout / 1000;
|
for (const auto &p : listen_sockets_) {
|
||||||
timeout.tv_usec = (mstimeout - (timeout.tv_sec*1000)) * 1000;
|
struct pollfd &pfd = pollvec[index++];
|
||||||
int status = select(nfds, &rfds, &wfds, &efds, &timeout);
|
pfd.fd = p.second;
|
||||||
|
pfd.events = POLLIN;
|
||||||
|
}
|
||||||
|
for (const ChanInfo &chan : chans_) {
|
||||||
|
struct pollfd &pfd = pollvec[index++];
|
||||||
|
pfd.fd = chan.socket;
|
||||||
|
pfd.events = POLLIN;
|
||||||
|
if (!driven_->drv_outgoing_empty(chan.chid)) {
|
||||||
|
pfd.events |= POLLOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct pollfd &stdiopoll = pollvec[index++];
|
||||||
|
stdiopoll.fd = 0;
|
||||||
|
stdiopoll.events = POLLIN;
|
||||||
|
|
||||||
|
// Do the poll.
|
||||||
|
int status = poll(&pollvec[0], pollvec.size(), mstimeout);
|
||||||
assert(status >= 0);
|
assert(status >= 0);
|
||||||
|
|
||||||
|
// Check listening sockets.
|
||||||
|
index = 0;
|
||||||
for (auto &p : listen_sockets_) {
|
for (auto &p : listen_sockets_) {
|
||||||
if (FD_ISSET(p.second, &rfds) || FD_ISSET(p.second, &efds)) {
|
struct pollfd &pfd = pollvec[index++];
|
||||||
|
if (pfd.revents & (POLLIN | POLLERR)) {
|
||||||
accept_connections(p.first, p.second);
|
accept_connections(p.first, p.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transfer bytes wherever possible.
|
||||||
for (ChanInfo &chan : chans_) {
|
for (ChanInfo &chan : chans_) {
|
||||||
|
struct pollfd &pfd = pollvec[index++];
|
||||||
SOCKET sock = chan.socket;
|
SOCKET sock = chan.socket;
|
||||||
if (sock == INVALID_SOCKET) continue;
|
if (sock == INVALID_SOCKET) continue;
|
||||||
if (FD_ISSET(sock, &wfds)) {
|
if (pfd.revents & POLLOUT) {
|
||||||
|
int nbytes; const char *bytes;
|
||||||
chan.state = CHAN_OPEN;
|
chan.state = CHAN_OPEN;
|
||||||
driven_->drv_peek_outgoing(chan.chid, &nbytes, &bytes);
|
driven_->drv_peek_outgoing(chan.chid, &nbytes, &bytes);
|
||||||
if (nbytes > 0) {
|
if (nbytes > 0) {
|
||||||
@@ -356,7 +378,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (FD_ISSET(sock, &rfds) || FD_ISSET(sock, &efds)) {
|
if (pfd.revents & (POLLIN | POLLERR)) {
|
||||||
// Someday, find a way to avoid this copy.
|
// Someday, find a way to avoid this copy.
|
||||||
int nrecv = recv(sock, chbuf.get(), 65536, 0);
|
int nrecv = recv(sock, chbuf.get(), 65536, 0);
|
||||||
if (nrecv <= 0) {
|
if (nrecv <= 0) {
|
||||||
@@ -368,6 +390,8 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete any newly-inactive channels
|
||||||
cleanup_channels();
|
cleanup_channels();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user