@@ -18,6 +18,20 @@ use sys_common::poison::{self, LockResult};
1818use sys:: time:: SteadyTime ;
1919use time:: Duration ;
2020
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+
2135/// A Condition Variable
2236///
2337/// Condition variables represent the ability to block a thread such that it
@@ -170,16 +184,16 @@ impl Condvar {
170184 /// preemption or platform differences that may not cause the maximum
171185 /// amount of time waited to be precisely `dur`.
172186 ///
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.
175189 ///
176190 /// Like `wait`, the lock specified will be re-acquired when this function
177191 /// returns, regardless of whether the timeout elapsed or not.
178192 #[ unstable( feature = "wait_timeout" , reason = "waiting for Duration" ,
179193 issue = "27772" ) ]
180194 pub fn wait_timeout < ' a , T > ( & self , guard : MutexGuard < ' a , T > ,
181195 dur : Duration )
182- -> LockResult < ( MutexGuard < ' a , T > , bool ) > {
196+ -> LockResult < ( MutexGuard < ' a , T > , WaitTimeoutResult ) > {
183197 unsafe {
184198 let me: & ' static Condvar = & * ( self as * const _ ) ;
185199 me. inner . wait_timeout ( guard, dur)
@@ -199,7 +213,7 @@ impl Condvar {
199213 guard : MutexGuard < ' a , T > ,
200214 dur : Duration ,
201215 f : F )
202- -> LockResult < ( MutexGuard < ' a , T > , bool ) >
216+ -> LockResult < ( MutexGuard < ' a , T > , WaitTimeoutResult ) >
203217 where F : FnMut ( LockResult < & mut T > ) -> bool {
204218 unsafe {
205219 let me: & ' static Condvar = & * ( self as * const _ ) ;
@@ -278,7 +292,13 @@ impl StaticCondvar {
278292 issue = "27717" ) ]
279293 pub fn wait_timeout_ms < ' a , T > ( & ' static self , guard : MutexGuard < ' a , T > , ms : u32 )
280294 -> 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+ }
282302 }
283303
284304 /// Waits on this condition variable for a notification, timing out after a
@@ -291,17 +311,17 @@ impl StaticCondvar {
291311 pub fn wait_timeout < ' a , T > ( & ' static self ,
292312 guard : MutexGuard < ' a , T > ,
293313 timeout : Duration )
294- -> LockResult < ( MutexGuard < ' a , T > , bool ) > {
295- let ( poisoned, success ) = unsafe {
314+ -> LockResult < ( MutexGuard < ' a , T > , WaitTimeoutResult ) > {
315+ let ( poisoned, result ) = unsafe {
296316 let lock = mutex:: guard_lock ( & guard) ;
297317 self . verify ( lock) ;
298318 let success = self . inner . wait_timeout ( lock, timeout) ;
299- ( mutex:: guard_poison ( & guard) . get ( ) , success)
319+ ( mutex:: guard_poison ( & guard) . get ( ) , WaitTimeoutResult ( ! success) )
300320 } ;
301321 if poisoned {
302- Err ( PoisonError :: new ( ( guard, success ) ) )
322+ Err ( PoisonError :: new ( ( guard, result ) ) )
303323 } else {
304- Ok ( ( guard, success ) )
324+ Ok ( ( guard, result ) )
305325 }
306326 }
307327
@@ -319,7 +339,7 @@ impl StaticCondvar {
319339 guard : MutexGuard < ' a , T > ,
320340 dur : Duration ,
321341 mut f : F )
322- -> LockResult < ( MutexGuard < ' a , T > , bool ) >
342+ -> LockResult < ( MutexGuard < ' a , T > , WaitTimeoutResult ) >
323343 where F : FnMut ( LockResult < & mut T > ) -> bool {
324344 // This could be made more efficient by pushing the implementation into
325345 // sys::condvar
@@ -332,28 +352,29 @@ impl StaticCondvar {
332352 let now = SteadyTime :: now ( ) ;
333353 let consumed = & now - & start;
334354 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 ) )
337357 } else {
338358 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 ) ,
340360 Err ( err) => {
341361 let ( new_guard, no_timeout) = err. into_inner ( ) ;
342362 ( Err ( PoisonError :: new ( new_guard) ) , no_timeout)
343363 }
344364 }
345365 } ;
346366 guard_result = new_guard_result;
347- if !no_timeout {
367+ if timed_out . timed_out ( ) {
348368 let result = f ( guard_result
349369 . as_mut ( )
350370 . map ( |g| & mut * * g)
351371 . map_err ( |e| PoisonError :: new ( & mut * * e. get_mut ( ) ) ) ) ;
372+ let result = WaitTimeoutResult ( !result) ;
352373 return poison:: map_result ( guard_result, |g| ( g, result) ) ;
353374 }
354375 }
355376
356- poison:: map_result ( guard_result, |g| ( g, true ) )
377+ poison:: map_result ( guard_result, |g| ( g, WaitTimeoutResult ( false ) ) )
357378 }
358379
359380 /// Wakes up one blocked thread on this condvar.
@@ -508,10 +529,10 @@ mod tests {
508529 static S : AtomicUsize = AtomicUsize :: new ( 0 ) ;
509530
510531 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 ) , |_| {
512533 false
513534 } ) . unwrap ( ) ;
514- assert ! ( !success ) ;
535+ assert ! ( timed_out . timed_out ( ) ) ;
515536
516537 let ( tx, rx) = channel ( ) ;
517538 let _t = thread:: spawn ( move || {
@@ -535,7 +556,7 @@ mod tests {
535556
536557 let mut state = 0 ;
537558 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 ) , |_| {
539560 assert_eq ! ( state, S . load( Ordering :: SeqCst ) ) ;
540561 tx. send ( ( ) ) . unwrap ( ) ;
541562 state += 1 ;
@@ -544,7 +565,7 @@ mod tests {
544565 _ => true ,
545566 }
546567 } ) . unwrap ( ) ;
547- assert ! ( success ) ;
568+ assert ! ( !timed_out . timed_out ( ) ) ;
548569 }
549570
550571 #[ test]
0 commit comments