File tree Expand file tree Collapse file tree 5 files changed +69
-0
lines changed Expand file tree Collapse file tree 5 files changed +69
-0
lines changed Original file line number Diff line number Diff 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 ///
Original file line number Diff line number Diff line change @@ -3,6 +3,7 @@ use libc::c_int;
33use std:: fs:: File ;
44use std:: io:: { self , Read , Write } ;
55use std:: mem;
6+ use std:: mem:: MaybeUninit ;
67use std:: os:: unix:: prelude:: * ;
78use std:: process:: Command ;
89use 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
Original file line number Diff line number Diff 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 }
Original file line number Diff line number Diff 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
Original file line number Diff line number Diff 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]
3761fn server_blocks ( ) {
3862 let c = t ! ( Client :: new( 1 ) ) ;
You can’t perform that action at this time.
0 commit comments