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 {
273
273
} )
274
274
}
275
275
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
+
276
289
/// Configures a child process to have access to this client's jobserver as
277
290
/// well.
278
291
///
Original file line number Diff line number Diff line change @@ -3,6 +3,7 @@ use libc::c_int;
3
3
use std:: fs:: File ;
4
4
use std:: io:: { self , Read , Write } ;
5
5
use std:: mem;
6
+ use std:: mem:: MaybeUninit ;
6
7
use std:: os:: unix:: prelude:: * ;
7
8
use std:: process:: Command ;
8
9
use std:: ptr;
@@ -204,6 +205,12 @@ impl Client {
204
205
format ! ( "{},{}" , self . read. as_raw_fd( ) , self . write. as_raw_fd( ) )
205
206
}
206
207
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
+
207
214
pub fn configure ( & self , cmd : & mut Command ) {
208
215
// Here we basically just want to say that in the child process
209
216
// 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 {
59
59
) ;
60
60
}
61
61
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
+
62
67
pub fn configure ( & self , _cmd : & mut Command ) {
63
68
unreachable ! ( ) ;
64
69
}
Original file line number Diff line number Diff line change @@ -170,6 +170,26 @@ impl Client {
170
170
self . name . clone ( )
171
171
}
172
172
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
+
173
193
pub fn configure ( & self , _cmd : & mut Command ) {
174
194
// nothing to do here, we gave the name of our semaphore to the
175
195
// child above
Original file line number Diff line number Diff line change @@ -33,6 +33,30 @@ fn server_multiple() {
33
33
drop ( ( a, b) ) ;
34
34
}
35
35
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
+
36
60
#[ test]
37
61
fn server_blocks ( ) {
38
62
let c = t ! ( Client :: new( 1 ) ) ;
You can’t perform that action at this time.
0 commit comments