@@ -18,6 +18,20 @@ use sys_common::poison::{self, LockResult};
18
18
use sys:: time:: SteadyTime ;
19
19
use time:: Duration ;
20
20
21
+ /// A type indicating whether a timed wait on a condition variable returned
22
+ /// due to a time out or not.
23
+ #[ derive( Debug , PartialEq , Eq , Copy , Clone ) ]
24
+ #[ unstable( feature = "wait_timeout" , reason = "newly added" , issue = "27772" ) ]
25
+ pub struct WaitTimeoutResult ( bool ) ;
26
+
27
+ impl WaitTimeoutResult {
28
+ /// Returns whether the wait was known to have timed out.
29
+ #[ unstable( feature = "wait_timeout" , reason = "newly added" , issue = "27772" ) ]
30
+ pub fn timed_out ( & self ) -> bool {
31
+ self . 0
32
+ }
33
+ }
34
+
21
35
/// A Condition Variable
22
36
///
23
37
/// Condition variables represent the ability to block a thread such that it
@@ -170,16 +184,16 @@ impl Condvar {
170
184
/// preemption or platform differences that may not cause the maximum
171
185
/// amount of time waited to be precisely `dur`.
172
186
///
173
- /// The returned boolean is `false` only if the timeout is known
174
- /// to have elapsed.
187
+ /// The returned `WaitTimeoutResult` value indicates if the timeout is
188
+ /// known to have elapsed.
175
189
///
176
190
/// Like `wait`, the lock specified will be re-acquired when this function
177
191
/// returns, regardless of whether the timeout elapsed or not.
178
192
#[ unstable( feature = "wait_timeout" , reason = "waiting for Duration" ,
179
193
issue = "27772" ) ]
180
194
pub fn wait_timeout < ' a , T > ( & self , guard : MutexGuard < ' a , T > ,
181
195
dur : Duration )
182
- -> LockResult < ( MutexGuard < ' a , T > , bool ) > {
196
+ -> LockResult < ( MutexGuard < ' a , T > , WaitTimeoutResult ) > {
183
197
unsafe {
184
198
let me: & ' static Condvar = & * ( self as * const _ ) ;
185
199
me. inner . wait_timeout ( guard, dur)
@@ -199,7 +213,7 @@ impl Condvar {
199
213
guard : MutexGuard < ' a , T > ,
200
214
dur : Duration ,
201
215
f : F )
202
- -> LockResult < ( MutexGuard < ' a , T > , bool ) >
216
+ -> LockResult < ( MutexGuard < ' a , T > , WaitTimeoutResult ) >
203
217
where F : FnMut ( LockResult < & mut T > ) -> bool {
204
218
unsafe {
205
219
let me: & ' static Condvar = & * ( self as * const _ ) ;
@@ -278,7 +292,13 @@ impl StaticCondvar {
278
292
issue = "27717" ) ]
279
293
pub fn wait_timeout_ms < ' a , T > ( & ' static self , guard : MutexGuard < ' a , T > , ms : u32 )
280
294
-> LockResult < ( MutexGuard < ' a , T > , bool ) > {
281
- self . wait_timeout ( guard, Duration :: from_millis ( ms as u64 ) )
295
+ match self . wait_timeout ( guard, Duration :: from_millis ( ms as u64 ) ) {
296
+ Ok ( ( guard, timed_out) ) => Ok ( ( guard, !timed_out. timed_out ( ) ) ) ,
297
+ Err ( poison) => {
298
+ let ( guard, timed_out) = poison. into_inner ( ) ;
299
+ Err ( PoisonError :: new ( ( guard, !timed_out. timed_out ( ) ) ) )
300
+ }
301
+ }
282
302
}
283
303
284
304
/// Waits on this condition variable for a notification, timing out after a
@@ -291,17 +311,17 @@ impl StaticCondvar {
291
311
pub fn wait_timeout < ' a , T > ( & ' static self ,
292
312
guard : MutexGuard < ' a , T > ,
293
313
timeout : Duration )
294
- -> LockResult < ( MutexGuard < ' a , T > , bool ) > {
295
- let ( poisoned, success ) = unsafe {
314
+ -> LockResult < ( MutexGuard < ' a , T > , WaitTimeoutResult ) > {
315
+ let ( poisoned, result ) = unsafe {
296
316
let lock = mutex:: guard_lock ( & guard) ;
297
317
self . verify ( lock) ;
298
318
let success = self . inner . wait_timeout ( lock, timeout) ;
299
- ( mutex:: guard_poison ( & guard) . get ( ) , success)
319
+ ( mutex:: guard_poison ( & guard) . get ( ) , WaitTimeoutResult ( ! success) )
300
320
} ;
301
321
if poisoned {
302
- Err ( PoisonError :: new ( ( guard, success ) ) )
322
+ Err ( PoisonError :: new ( ( guard, result ) ) )
303
323
} else {
304
- Ok ( ( guard, success ) )
324
+ Ok ( ( guard, result ) )
305
325
}
306
326
}
307
327
@@ -319,7 +339,7 @@ impl StaticCondvar {
319
339
guard : MutexGuard < ' a , T > ,
320
340
dur : Duration ,
321
341
mut f : F )
322
- -> LockResult < ( MutexGuard < ' a , T > , bool ) >
342
+ -> LockResult < ( MutexGuard < ' a , T > , WaitTimeoutResult ) >
323
343
where F : FnMut ( LockResult < & mut T > ) -> bool {
324
344
// This could be made more efficient by pushing the implementation into
325
345
// sys::condvar
@@ -332,28 +352,29 @@ impl StaticCondvar {
332
352
let now = SteadyTime :: now ( ) ;
333
353
let consumed = & now - & start;
334
354
let guard = guard_result. unwrap_or_else ( |e| e. into_inner ( ) ) ;
335
- let ( new_guard_result, no_timeout ) = if consumed > dur {
336
- ( Ok ( guard) , false )
355
+ let ( new_guard_result, timed_out ) = if consumed > dur {
356
+ ( Ok ( guard) , WaitTimeoutResult ( true ) )
337
357
} else {
338
358
match self . wait_timeout ( guard, dur - consumed) {
339
- Ok ( ( new_guard, no_timeout ) ) => ( Ok ( new_guard) , no_timeout ) ,
359
+ Ok ( ( new_guard, timed_out ) ) => ( Ok ( new_guard) , timed_out ) ,
340
360
Err ( err) => {
341
361
let ( new_guard, no_timeout) = err. into_inner ( ) ;
342
362
( Err ( PoisonError :: new ( new_guard) ) , no_timeout)
343
363
}
344
364
}
345
365
} ;
346
366
guard_result = new_guard_result;
347
- if !no_timeout {
367
+ if timed_out . timed_out ( ) {
348
368
let result = f ( guard_result
349
369
. as_mut ( )
350
370
. map ( |g| & mut * * g)
351
371
. map_err ( |e| PoisonError :: new ( & mut * * e. get_mut ( ) ) ) ) ;
372
+ let result = WaitTimeoutResult ( !result) ;
352
373
return poison:: map_result ( guard_result, |g| ( g, result) ) ;
353
374
}
354
375
}
355
376
356
- poison:: map_result ( guard_result, |g| ( g, true ) )
377
+ poison:: map_result ( guard_result, |g| ( g, WaitTimeoutResult ( false ) ) )
357
378
}
358
379
359
380
/// Wakes up one blocked thread on this condvar.
@@ -508,10 +529,10 @@ mod tests {
508
529
static S : AtomicUsize = AtomicUsize :: new ( 0 ) ;
509
530
510
531
let g = M . lock ( ) . unwrap ( ) ;
511
- let ( g, success ) = C . wait_timeout_with ( g, Duration :: new ( 0 , 1000 ) , |_| {
532
+ let ( g, timed_out ) = C . wait_timeout_with ( g, Duration :: new ( 0 , 1000 ) , |_| {
512
533
false
513
534
} ) . unwrap ( ) ;
514
- assert ! ( !success ) ;
535
+ assert ! ( timed_out . timed_out ( ) ) ;
515
536
516
537
let ( tx, rx) = channel ( ) ;
517
538
let _t = thread:: spawn ( move || {
@@ -535,7 +556,7 @@ mod tests {
535
556
536
557
let mut state = 0 ;
537
558
let day = 24 * 60 * 60 ;
538
- let ( _g, success ) = C . wait_timeout_with ( g, Duration :: new ( day, 0 ) , |_| {
559
+ let ( _g, timed_out ) = C . wait_timeout_with ( g, Duration :: new ( day, 0 ) , |_| {
539
560
assert_eq ! ( state, S . load( Ordering :: SeqCst ) ) ;
540
561
tx. send ( ( ) ) . unwrap ( ) ;
541
562
state += 1 ;
@@ -544,7 +565,7 @@ mod tests {
544
565
_ => true ,
545
566
}
546
567
} ) . unwrap ( ) ;
547
- assert ! ( success ) ;
568
+ assert ! ( !timed_out . timed_out ( ) ) ;
548
569
}
549
570
550
571
#[ test]
0 commit comments