@@ -21,7 +21,7 @@ impl Drop for JobToken {
21
21
}
22
22
}
23
23
24
- pub ( crate ) enum JobTokenServer {
24
+ enum JobTokenServer {
25
25
Inherited ( inherited_jobserver:: JobServer ) ,
26
26
InProcess ( inprocess_jobserver:: JobServer ) ,
27
27
}
@@ -35,7 +35,7 @@ impl JobTokenServer {
35
35
/// present), we will create a global in-process only jobserver
36
36
/// that has to be static so that it will be shared by all cc
37
37
/// compilation.
38
- pub ( crate ) fn new ( ) -> & ' static Self {
38
+ fn new ( ) -> & ' static Self {
39
39
static INIT : Once = Once :: new ( ) ;
40
40
static mut JOBSERVER : MaybeUninit < JobTokenServer > = MaybeUninit :: uninit ( ) ;
41
41
@@ -50,11 +50,35 @@ impl JobTokenServer {
50
50
& * JOBSERVER . as_ptr ( )
51
51
}
52
52
}
53
+ }
54
+
55
+ pub ( crate ) struct ActiveJobTokenServer ( & ' static JobTokenServer ) ;
56
+
57
+ impl ActiveJobTokenServer {
58
+ pub ( crate ) fn new ( ) -> Result < Self , Error > {
59
+ let jobserver = JobTokenServer :: new ( ) ;
60
+
61
+ #[ cfg( unix) ]
62
+ if let JobTokenServer :: Inherited ( inherited_jobserver) = & jobserver {
63
+ inherited_jobserver. enter_active ( ) ?;
64
+ }
65
+
66
+ Ok ( Self ( jobserver) )
67
+ }
53
68
54
69
pub ( crate ) fn try_acquire ( & self ) -> Result < Option < JobToken > , Error > {
55
- match self {
56
- Self :: Inherited ( jobserver) => jobserver. try_acquire ( ) ,
57
- Self :: InProcess ( jobserver) => Ok ( jobserver. try_acquire ( ) ) ,
70
+ match & self . 0 {
71
+ JobTokenServer :: Inherited ( jobserver) => jobserver. try_acquire ( ) ,
72
+ JobTokenServer :: InProcess ( jobserver) => Ok ( jobserver. try_acquire ( ) ) ,
73
+ }
74
+ }
75
+ }
76
+
77
+ impl Drop for ActiveJobTokenServer {
78
+ fn drop ( & mut self ) {
79
+ #[ cfg( unix) ]
80
+ if let JobTokenServer :: Inherited ( inherited_jobserver) = & self . 0 {
81
+ inherited_jobserver. exit_active ( ) ;
58
82
}
59
83
}
60
84
}
@@ -70,6 +94,9 @@ mod inherited_jobserver {
70
94
} ,
71
95
} ;
72
96
97
+ #[ cfg( unix) ]
98
+ use std:: sync:: { Mutex , MutexGuard , PoisonError } ;
99
+
73
100
pub ( crate ) struct JobServer {
74
101
/// Implicit token for this process which is obtained and will be
75
102
/// released in parent. Since JobTokens only give back what they got,
@@ -80,6 +107,10 @@ mod inherited_jobserver {
80
107
/// the end of the process.
81
108
global_implicit_token : AtomicBool ,
82
109
inner : sys:: JobServerClient ,
110
+ /// number of active clients is required to know when it is safe to clear non-blocking
111
+ /// flags
112
+ #[ cfg( unix) ]
113
+ active_clients_cnt : Mutex < usize > ,
83
114
}
84
115
85
116
impl JobServer {
@@ -117,9 +148,40 @@ mod inherited_jobserver {
117
148
. map ( |inner| Self {
118
149
inner,
119
150
global_implicit_token : AtomicBool :: new ( true ) ,
151
+ #[ cfg( unix) ]
152
+ active_clients_cnt : Mutex :: new ( 0 ) ,
120
153
} )
121
154
}
122
155
156
+ #[ cfg( unix) ]
157
+ fn get_locked_active_cnt ( & self ) -> MutexGuard < ' _ , usize > {
158
+ self . active_clients_cnt
159
+ . lock ( )
160
+ . unwrap_or_else ( PoisonError :: into_inner)
161
+ }
162
+
163
+ #[ cfg( unix) ]
164
+ pub ( super ) fn enter_active ( & self ) -> Result < ( ) , Error > {
165
+ let mut active_cnt = self . get_locked_active_cnt ( ) ;
166
+ if * active_cnt == 0 {
167
+ self . inner . prepare_for_acquires ( ) ?;
168
+ }
169
+
170
+ * active_cnt += 1 ;
171
+
172
+ Ok ( ( ) )
173
+ }
174
+
175
+ #[ cfg( unix) ]
176
+ pub ( super ) fn exit_active ( & self ) {
177
+ let mut active_cnt = self . get_locked_active_cnt ( ) ;
178
+ * active_cnt -= 1 ;
179
+
180
+ if * active_cnt == 0 {
181
+ self . inner . done_acquires ( ) ;
182
+ }
183
+ }
184
+
123
185
pub ( super ) fn try_acquire ( & self ) -> Result < Option < JobToken > , Error > {
124
186
if !self . global_implicit_token . swap ( false , AcqRel ) {
125
187
// Cold path, no global implicit token, obtain one
0 commit comments