Skip to content

Commit eaa0458

Browse files
authored
Merge pull request #31 from the8472/optimistic-read
Try blocking reads first to avoid thundering herd problem
2 parents 9d5e6da + c8aa598 commit eaa0458

File tree

1 file changed

+21
-16
lines changed

1 file changed

+21
-16
lines changed

src/unix.rs

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,11 @@ impl Client {
122122
// fds are set to nonblocking and combined with `pselect`
123123
// internally.
124124
//
125-
// Here we try to be compatible with both strategies. We
126-
// unconditionally expect the file descriptor to be in nonblocking
127-
// mode and if it happens to be in blocking mode then most of this
128-
// won't end up actually being necessary!
125+
// Here we try to be compatible with both strategies. We optimistically
126+
// try to read from the file descriptor which then may block, return
127+
// a token or indicate that polling is needed.
128+
// Blocking reads (if possible) allows the kernel to be more selective
129+
// about which readers to wake up when a token is written to the pipe.
129130
//
130131
// We use `poll` here to block this thread waiting for read
131132
// readiness, and then afterwards we perform the `read` itself. If
@@ -139,17 +140,6 @@ impl Client {
139140
fd.fd = self.read.as_raw_fd();
140141
fd.events = libc::POLLIN;
141142
loop {
142-
fd.revents = 0;
143-
if libc::poll(&mut fd, 1, -1) == -1 {
144-
let e = io::Error::last_os_error();
145-
match e.kind() {
146-
io::ErrorKind::Interrupted => return Ok(None),
147-
_ => return Err(e),
148-
}
149-
}
150-
if fd.revents == 0 {
151-
continue;
152-
}
153143
let mut buf = [0];
154144
match (&self.read).read(&mut buf) {
155145
Ok(1) => return Ok(Some(Acquired { byte: buf[0] })),
@@ -160,10 +150,25 @@ impl Client {
160150
))
161151
}
162152
Err(e) => match e.kind() {
163-
io::ErrorKind::WouldBlock | io::ErrorKind::Interrupted => return Ok(None),
153+
io::ErrorKind::WouldBlock => { /* fall through to polling */ }
154+
io::ErrorKind::Interrupted => return Ok(None),
164155
_ => return Err(e),
165156
},
166157
}
158+
159+
loop {
160+
fd.revents = 0;
161+
if libc::poll(&mut fd, 1, -1) == -1 {
162+
let e = io::Error::last_os_error();
163+
return match e.kind() {
164+
io::ErrorKind::Interrupted => Ok(None),
165+
_ => Err(e),
166+
};
167+
}
168+
if fd.revents != 0 {
169+
break;
170+
}
171+
}
167172
}
168173
}
169174
}

0 commit comments

Comments
 (0)