1- use jobserver_crate:: { Client , HelperThread , Acquired } ;
1+ use jobserver_crate:: Client ;
22use lazy_static:: lazy_static;
3- use std:: sync:: { Condvar , Arc , Mutex } ;
4- use std:: mem;
5-
6- #[ derive( Default ) ]
7- struct LockedProxyData {
8- /// The number of free thread tokens, this may include the implicit token given to the process
9- free : usize ,
10-
11- /// The number of threads waiting for a token
12- waiters : usize ,
13-
14- /// The number of tokens we requested from the server
15- requested : usize ,
16-
17- /// Stored tokens which will be dropped when we no longer need them
18- tokens : Vec < Acquired > ,
19- }
20-
21- impl LockedProxyData {
22- fn request_token ( & mut self , thread : & Mutex < HelperThread > ) {
23- self . requested += 1 ;
24- thread. lock ( ) . unwrap ( ) . request_token ( ) ;
25- }
26-
27- fn release_token ( & mut self , cond_var : & Condvar ) {
28- if self . waiters > 0 {
29- self . free += 1 ;
30- cond_var. notify_one ( ) ;
31- } else {
32- if self . tokens . is_empty ( ) {
33- // We are returning the implicit token
34- self . free += 1 ;
35- } else {
36- // Return a real token to the server
37- self . tokens . pop ( ) . unwrap ( ) ;
38- }
39- }
40- }
41-
42- fn take_token ( & mut self , thread : & Mutex < HelperThread > ) -> bool {
43- if self . free > 0 {
44- self . free -= 1 ;
45- self . waiters -= 1 ;
46-
47- // We stole some token reqested by someone else
48- // Request another one
49- if self . requested + self . free < self . waiters {
50- self . request_token ( thread) ;
51- }
52-
53- true
54- } else {
55- false
56- }
57- }
58-
59- fn new_requested_token ( & mut self , token : Acquired , cond_var : & Condvar ) {
60- self . requested -= 1 ;
61-
62- // Does anything need this token?
63- if self . waiters > 0 {
64- self . free += 1 ;
65- self . tokens . push ( token) ;
66- cond_var. notify_one ( ) ;
67- } else {
68- // Otherwise we'll just drop it
69- mem:: drop ( token) ;
70- }
71- }
72- }
73-
74- #[ derive( Default ) ]
75- struct ProxyData {
76- lock : Mutex < LockedProxyData > ,
77- cond_var : Condvar ,
78- }
79-
80- /// A helper type which makes managing jobserver tokens easier.
81- /// It also allows you to treat the implicit token given to the process
82- /// in the same manner as requested tokens.
83- struct Proxy {
84- thread : Mutex < HelperThread > ,
85- data : Arc < ProxyData > ,
86- }
873
884lazy_static ! {
895 // We can only call `from_env` once per process
@@ -105,52 +21,22 @@ lazy_static! {
10521 // per-process.
10622 static ref GLOBAL_CLIENT : Client = unsafe {
10723 Client :: from_env( ) . unwrap_or_else( || {
108- Client :: new( 32 ) . expect( "failed to create jobserver" )
24+ let client = Client :: new( 32 ) . expect( "failed to create jobserver" ) ;
25+ // Acquire a token for the main thread which we can release later
26+ client. acquire_raw( ) . ok( ) ;
27+ client
10928 } )
11029 } ;
111-
112- static ref GLOBAL_PROXY : Proxy = {
113- let data = Arc :: new( ProxyData :: default ( ) ) ;
114-
115- Proxy {
116- data: data. clone( ) ,
117- thread: Mutex :: new( client( ) . into_helper_thread( move |token| {
118- data. lock. lock( ) . unwrap( ) . new_requested_token( token. unwrap( ) , & data. cond_var) ;
119- } ) . unwrap( ) ) ,
120- }
121- } ;
12230}
12331
12432pub fn client ( ) -> Client {
12533 GLOBAL_CLIENT . clone ( )
12634}
12735
12836pub fn acquire_thread ( ) {
129- GLOBAL_PROXY . acquire_token ( ) ;
37+ GLOBAL_CLIENT . acquire_raw ( ) . ok ( ) ;
13038}
13139
13240pub fn release_thread ( ) {
133- GLOBAL_PROXY . release_token ( ) ;
134- }
135-
136- impl Proxy {
137- fn release_token ( & self ) {
138- self . data . lock . lock ( ) . unwrap ( ) . release_token ( & self . data . cond_var ) ;
139- }
140-
141- fn acquire_token ( & self ) {
142- let mut data = self . data . lock . lock ( ) . unwrap ( ) ;
143- data. waiters += 1 ;
144- if data. take_token ( & self . thread ) {
145- return ;
146- }
147- // Request a token for us
148- data. request_token ( & self . thread ) ;
149- loop {
150- data = self . data . cond_var . wait ( data) . unwrap ( ) ;
151- if data. take_token ( & self . thread ) {
152- return ;
153- }
154- }
155- }
41+ GLOBAL_CLIENT . release_raw ( ) . ok ( ) ;
15642}
0 commit comments