Skip to content

Commit d7a5828

Browse files
authored
Merge pull request #45 from olofj/add-available
Add `available` traits to find out how many client tokens are unused
2 parents 2c7fbf0 + cfae7ff commit d7a5828

File tree

5 files changed

+69
-0
lines changed

5 files changed

+69
-0
lines changed

src/lib.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,19 @@ impl Client {
273273
})
274274
}
275275

276+
/// Returns amount of tokens in the read-side pipe.
277+
///
278+
/// # Return value
279+
///
280+
/// Number of bytes available to be read from the jobserver pipe
281+
///
282+
/// # Errors
283+
///
284+
/// Underlying errors from the ioctl will be passed up.
285+
pub fn available(&self) -> io::Result<usize> {
286+
self.inner.available()
287+
}
288+
276289
/// Configures a child process to have access to this client's jobserver as
277290
/// well.
278291
///

src/unix.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use libc::c_int;
33
use std::fs::File;
44
use std::io::{self, Read, Write};
55
use std::mem;
6+
use std::mem::MaybeUninit;
67
use std::os::unix::prelude::*;
78
use std::process::Command;
89
use std::ptr;
@@ -204,6 +205,12 @@ impl Client {
204205
format!("{},{}", self.read.as_raw_fd(), self.write.as_raw_fd())
205206
}
206207

208+
pub fn available(&self) -> io::Result<usize> {
209+
let mut len = MaybeUninit::<c_int>::uninit();
210+
cvt(unsafe { libc::ioctl(self.read.as_raw_fd(), libc::FIONREAD, len.as_mut_ptr()) })?;
211+
Ok(unsafe { len.assume_init() } as usize)
212+
}
213+
207214
pub fn configure(&self, cmd: &mut Command) {
208215
// Here we basically just want to say that in the child process
209216
// we'll configure the read/write file descriptors to *not* be

src/wasm.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ impl Client {
5959
);
6060
}
6161

62+
pub fn available(&self) -> io::Result<usize> {
63+
let lock = self.inner.count.lock().unwrap_or_else(|e| e.into_inner());
64+
Ok(*lock)
65+
}
66+
6267
pub fn configure(&self, _cmd: &mut Command) {
6368
unreachable!();
6469
}

src/windows.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,26 @@ impl Client {
170170
self.name.clone()
171171
}
172172

173+
pub fn available(&self) -> io::Result<usize> {
174+
// Can't read value of a semaphore on Windows, so
175+
// try to acquire without sleeping, since we can find out the
176+
// old value on release. If acquisiton fails, then available is 0.
177+
unsafe {
178+
let r = WaitForSingleObject(self.sem.0, 0);
179+
if r != WAIT_OBJECT_0 {
180+
Ok(0)
181+
} else {
182+
let mut prev: LONG = 0;
183+
let r = ReleaseSemaphore(self.sem.0, 1, &mut prev);
184+
if r != 0 {
185+
Ok(prev as usize + 1)
186+
} else {
187+
Err(io::Error::last_os_error())
188+
}
189+
}
190+
}
191+
}
192+
173193
pub fn configure(&self, _cmd: &mut Command) {
174194
// nothing to do here, we gave the name of our semaphore to the
175195
// child above

tests/server.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,30 @@ fn server_multiple() {
3333
drop((a, b));
3434
}
3535

36+
#[test]
37+
fn server_available() {
38+
let c = t!(Client::new(10));
39+
assert_eq!(c.available().unwrap(), 10);
40+
let a = c.acquire().unwrap();
41+
assert_eq!(c.available().unwrap(), 9);
42+
drop(a);
43+
assert_eq!(c.available().unwrap(), 10);
44+
}
45+
46+
#[test]
47+
fn server_none_available() {
48+
let c = t!(Client::new(2));
49+
assert_eq!(c.available().unwrap(), 2);
50+
let a = c.acquire().unwrap();
51+
assert_eq!(c.available().unwrap(), 1);
52+
let b = c.acquire().unwrap();
53+
assert_eq!(c.available().unwrap(), 0);
54+
drop(a);
55+
assert_eq!(c.available().unwrap(), 1);
56+
drop(b);
57+
assert_eq!(c.available().unwrap(), 2);
58+
}
59+
3660
#[test]
3761
fn server_blocks() {
3862
let c = t!(Client::new(1));

0 commit comments

Comments
 (0)