@@ -69,20 +69,20 @@ pub struct Condvar { inner: Box<StaticCondvar> }
69
69
/// # Examples
70
70
///
71
71
/// ```
72
- /// # #![feature(std_misc )]
72
+ /// # #![feature(static_condvar )]
73
73
/// use std::sync::{StaticCondvar, CONDVAR_INIT};
74
74
///
75
75
/// static CVAR: StaticCondvar = CONDVAR_INIT;
76
76
/// ```
77
- #[ unstable( feature = "std_misc " ,
77
+ #[ unstable( feature = "static_condvar " ,
78
78
reason = "may be merged with Condvar in the future" ) ]
79
79
pub struct StaticCondvar {
80
80
inner : sys:: Condvar ,
81
81
mutex : AtomicUsize ,
82
82
}
83
83
84
84
/// Constant initializer for a statically allocated condition variable.
85
- #[ unstable( feature = "std_misc " ,
85
+ #[ unstable( feature = "static_condvar " ,
86
86
reason = "may be merged with Condvar in the future" ) ]
87
87
pub const CONDVAR_INIT : StaticCondvar = StaticCondvar {
88
88
inner : sys:: CONDVAR_INIT ,
@@ -161,6 +161,30 @@ impl Condvar {
161
161
}
162
162
}
163
163
164
+ /// Waits on this condition variable for a notification, timing out after a
165
+ /// specified duration.
166
+ ///
167
+ /// The semantics of this function are equivalent to `wait()` except that
168
+ /// the thread will be blocked for roughly no longer than `dur`. This
169
+ /// method should not be used for precise timing due to anomalies such as
170
+ /// preemption or platform differences that may not cause the maximum
171
+ /// amount of time waited to be precisely `dur`.
172
+ ///
173
+ /// The returned boolean is `false` only if the timeout is known
174
+ /// to have elapsed.
175
+ ///
176
+ /// Like `wait`, the lock specified will be re-acquired when this function
177
+ /// returns, regardless of whether the timeout elapsed or not.
178
+ #[ unstable( feature = "wait_timeout" , reason = "waiting for Duration" ) ]
179
+ pub fn wait_timeout < ' a , T > ( & self , guard : MutexGuard < ' a , T > ,
180
+ dur : Duration )
181
+ -> LockResult < ( MutexGuard < ' a , T > , bool ) > {
182
+ unsafe {
183
+ let me: & ' static Condvar = & * ( self as * const _ ) ;
184
+ me. inner . wait_timeout ( guard, dur)
185
+ }
186
+ }
187
+
164
188
/// Waits on this condition variable for a notification, timing out after a
165
189
/// specified duration.
166
190
///
@@ -214,7 +238,7 @@ impl StaticCondvar {
214
238
/// notification.
215
239
///
216
240
/// See `Condvar::wait`.
217
- #[ unstable( feature = "std_misc " ,
241
+ #[ unstable( feature = "static_condvar " ,
218
242
reason = "may be merged with Condvar in the future" ) ]
219
243
pub fn wait < ' a , T > ( & ' static self , guard : MutexGuard < ' a , T > )
220
244
-> LockResult < MutexGuard < ' a , T > > {
@@ -235,14 +259,27 @@ impl StaticCondvar {
235
259
/// specified duration.
236
260
///
237
261
/// See `Condvar::wait_timeout`.
238
- #[ unstable( feature = "std_misc " ,
262
+ #[ unstable( feature = "static_condvar " ,
239
263
reason = "may be merged with Condvar in the future" ) ]
240
264
pub fn wait_timeout_ms < ' a , T > ( & ' static self , guard : MutexGuard < ' a , T > , ms : u32 )
241
265
-> LockResult < ( MutexGuard < ' a , T > , bool ) > {
266
+ self . wait_timeout ( guard, Duration :: from_millis ( ms as u64 ) )
267
+ }
268
+
269
+ /// Waits on this condition variable for a notification, timing out after a
270
+ /// specified duration.
271
+ ///
272
+ /// See `Condvar::wait_timeout`.
273
+ #[ unstable( feature = "static_condvar" ,
274
+ reason = "may be merged with Condvar in the future" ) ]
275
+ pub fn wait_timeout < ' a , T > ( & ' static self ,
276
+ guard : MutexGuard < ' a , T > ,
277
+ timeout : Duration )
278
+ -> LockResult < ( MutexGuard < ' a , T > , bool ) > {
242
279
let ( poisoned, success) = unsafe {
243
280
let lock = mutex:: guard_lock ( & guard) ;
244
281
self . verify ( lock) ;
245
- let success = self . inner . wait_timeout ( lock, Duration :: milliseconds ( ms as i64 ) ) ;
282
+ let success = self . inner . wait_timeout ( lock, timeout ) ;
246
283
( mutex:: guard_poison ( & guard) . get ( ) , success)
247
284
} ;
248
285
if poisoned {
@@ -259,15 +296,16 @@ impl StaticCondvar {
259
296
/// passed and the function returns `false`.
260
297
///
261
298
/// See `Condvar::wait_timeout_with`.
262
- #[ unstable( feature = "std_misc " ,
299
+ #[ unstable( feature = "static_condvar " ,
263
300
reason = "may be merged with Condvar in the future" ) ]
264
301
pub fn wait_timeout_with < ' a , T , F > ( & ' static self ,
265
302
guard : MutexGuard < ' a , T > ,
266
303
dur : Duration ,
267
304
mut f : F )
268
305
-> LockResult < ( MutexGuard < ' a , T > , bool ) >
269
306
where F : FnMut ( LockResult < & mut T > ) -> bool {
270
- // This could be made more efficient by pushing the implementation into sys::condvar
307
+ // This could be made more efficient by pushing the implementation into
308
+ // sys::condvar
271
309
let start = SteadyTime :: now ( ) ;
272
310
let mut guard_result: LockResult < MutexGuard < ' a , T > > = Ok ( guard) ;
273
311
while !f ( guard_result
@@ -277,12 +315,15 @@ impl StaticCondvar {
277
315
let now = SteadyTime :: now ( ) ;
278
316
let consumed = & now - & start;
279
317
let guard = guard_result. unwrap_or_else ( |e| e. into_inner ( ) ) ;
280
- let res = self . wait_timeout_ms ( guard, ( dur - consumed) . num_milliseconds ( ) as u32 ) ;
281
- let ( new_guard_result, no_timeout) = match res {
282
- Ok ( ( new_guard, no_timeout) ) => ( Ok ( new_guard) , no_timeout) ,
283
- Err ( err) => {
284
- let ( new_guard, no_timeout) = err. into_inner ( ) ;
285
- ( Err ( PoisonError :: new ( new_guard) ) , no_timeout)
318
+ let ( new_guard_result, no_timeout) = if consumed > dur {
319
+ ( Ok ( guard) , false )
320
+ } else {
321
+ match self . wait_timeout ( guard, dur - consumed) {
322
+ Ok ( ( new_guard, no_timeout) ) => ( Ok ( new_guard) , no_timeout) ,
323
+ Err ( err) => {
324
+ let ( new_guard, no_timeout) = err. into_inner ( ) ;
325
+ ( Err ( PoisonError :: new ( new_guard) ) , no_timeout)
326
+ }
286
327
}
287
328
} ;
288
329
guard_result = new_guard_result;
@@ -301,14 +342,14 @@ impl StaticCondvar {
301
342
/// Wakes up one blocked thread on this condvar.
302
343
///
303
344
/// See `Condvar::notify_one`.
304
- #[ unstable( feature = "std_misc " ,
345
+ #[ unstable( feature = "static_condvar " ,
305
346
reason = "may be merged with Condvar in the future" ) ]
306
347
pub fn notify_one ( & ' static self ) { unsafe { self . inner . notify_one ( ) } }
307
348
308
349
/// Wakes up all blocked threads on this condvar.
309
350
///
310
351
/// See `Condvar::notify_all`.
311
- #[ unstable( feature = "std_misc " ,
352
+ #[ unstable( feature = "static_condvar " ,
312
353
reason = "may be merged with Condvar in the future" ) ]
313
354
pub fn notify_all ( & ' static self ) { unsafe { self . inner . notify_all ( ) } }
314
355
@@ -318,7 +359,7 @@ impl StaticCondvar {
318
359
/// active users of the condvar, and this also doesn't prevent any future
319
360
/// users of the condvar. This method is required to be called to not leak
320
361
/// memory on all platforms.
321
- #[ unstable( feature = "std_misc " ,
362
+ #[ unstable( feature = "static_condvar " ,
322
363
reason = "may be merged with Condvar in the future" ) ]
323
364
pub unsafe fn destroy ( & ' static self ) {
324
365
self . inner . destroy ( )
@@ -447,7 +488,9 @@ mod tests {
447
488
static S : AtomicUsize = ATOMIC_USIZE_INIT ;
448
489
449
490
let g = M . lock ( ) . unwrap ( ) ;
450
- let ( g, success) = C . wait_timeout_with ( g, Duration :: nanoseconds ( 1000 ) , |_| false ) . unwrap ( ) ;
491
+ let ( g, success) = C . wait_timeout_with ( g, Duration :: new ( 0 , 1000 ) , |_| {
492
+ false
493
+ } ) . unwrap ( ) ;
451
494
assert ! ( !success) ;
452
495
453
496
let ( tx, rx) = channel ( ) ;
@@ -471,7 +514,8 @@ mod tests {
471
514
} ) ;
472
515
473
516
let mut state = 0 ;
474
- let ( _g, success) = C . wait_timeout_with ( g, Duration :: days ( 1 ) , |_| {
517
+ let day = 24 * 60 * 60 ;
518
+ let ( _g, success) = C . wait_timeout_with ( g, Duration :: new ( day, 0 ) , |_| {
475
519
assert_eq ! ( state, S . load( Ordering :: SeqCst ) ) ;
476
520
tx. send ( ( ) ) . unwrap ( ) ;
477
521
state += 1 ;
0 commit comments