1#[cfg(test)]
2mod tests;
3
4use crate::fmt;
5use crate::sync::{mutex, poison, LockResult, MutexGuard, PoisonError};
6use crate::sys::sync as sys;
7use crate::time::{Duration, Instant};
8
9/// A type indicating whether a timed wait on a condition variable returned
10/// due to a time out or not.
11///
12/// It is returned by the [`wait_timeout`] method.
13///
14/// [`wait_timeout`]: Condvar::wait_timeout
15#[derive(Debug, PartialEq, Eq, Copy, Clone)]
16#[stable(feature = "wait_timeout", since = "1.5.0")]
17pub struct WaitTimeoutResult(bool);
18
19impl WaitTimeoutResult {
20 /// Returns `true` if the wait was known to have timed out.
21 ///
22 /// # Examples
23 ///
24 /// This example spawns a thread which will sleep 20 milliseconds before
25 /// updating a boolean value and then notifying the condvar.
26 ///
27 /// The main thread will wait with a 10 millisecond timeout on the condvar
28 /// and will leave the loop upon timeout.
29 ///
30 /// ```
31 /// use std::sync::{Arc, Condvar, Mutex};
32 /// use std::thread;
33 /// use std::time::Duration;
34 ///
35 /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
36 /// let pair2 = Arc::clone(&pair);
37 ///
38 /// thread::spawn(move || {
39 /// let (lock, cvar) = &*pair2;
40 ///
41 /// // Let's wait 20 milliseconds before notifying the condvar.
42 /// thread::sleep(Duration::from_millis(20));
43 ///
44 /// let mut started = lock.lock().unwrap();
45 /// // We update the boolean value.
46 /// *started = true;
47 /// cvar.notify_one();
48 /// });
49 ///
50 /// // Wait for the thread to start up.
51 /// let (lock, cvar) = &*pair;
52 /// loop {
53 /// // Let's put a timeout on the condvar's wait.
54 /// let result = cvar.wait_timeout(lock.lock().unwrap(), Duration::from_millis(10)).unwrap();
55 /// // 10 milliseconds have passed.
56 /// if result.1.timed_out() {
57 /// // timed out now and we can leave.
58 /// break
59 /// }
60 /// }
61 /// ```
62 #[must_use]
63 #[stable(feature = "wait_timeout", since = "1.5.0")]
64 pub fn timed_out(&self) -> bool {
65 self.0
66 }
67}
68
69/// A Condition Variable
70///
71/// Condition variables represent the ability to block a thread such that it
72/// consumes no CPU time while waiting for an event to occur. Condition
73/// variables are typically associated with a boolean predicate (a condition)
74/// and a mutex. The predicate is always verified inside of the mutex before
75/// determining that a thread must block.
76///
77/// Functions in this module will block the current **thread** of execution.
78/// Note that any attempt to use multiple mutexes on the same condition
79/// variable may result in a runtime panic.
80///
81/// # Examples
82///
83/// ```
84/// use std::sync::{Arc, Mutex, Condvar};
85/// use std::thread;
86///
87/// let pair = Arc::new((Mutex::new(false), Condvar::new()));
88/// let pair2 = Arc::clone(&pair);
89///
90/// // Inside of our lock, spawn a new thread, and then wait for it to start.
91/// thread::spawn(move|| {
92/// let (lock, cvar) = &*pair2;
93/// let mut started = lock.lock().unwrap();
94/// *started = true;
95/// // We notify the condvar that the value has changed.
96/// cvar.notify_one();
97/// });
98///
99/// // Wait for the thread to start up.
100/// let (lock, cvar) = &*pair;
101/// let mut started = lock.lock().unwrap();
102/// while !*started {
103/// started = cvar.wait(started).unwrap();
104/// }
105/// ```
106#[stable(feature = "rust1", since = "1.0.0")]
107pub struct Condvar {
108 inner: sys::Condvar,
109}
110
111impl Condvar {
112 /// Creates a new condition variable which is ready to be waited on and
113 /// notified.
114 ///
115 /// # Examples
116 ///
117 /// ```
118 /// use std::sync::Condvar;
119 ///
120 /// let condvar = Condvar::new();
121 /// ```
122 #[stable(feature = "rust1", since = "1.0.0")]
123 #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
124 #[must_use]
125 #[inline]
126 pub const fn new() -> Condvar {
127 Condvar { inner: sys::Condvar::new() }
128 }
129
130 /// Blocks the current thread until this condition variable receives a
131 /// notification.
132 ///
133 /// This function will atomically unlock the mutex specified (represented by
134 /// `guard`) and block the current thread. This means that any calls
135 /// to [`notify_one`] or [`notify_all`] which happen logically after the
136 /// mutex is unlocked are candidates to wake this thread up. When this
137 /// function call returns, the lock specified will have been re-acquired.
138 ///
139 /// Note that this function is susceptible to spurious wakeups. Condition
140 /// variables normally have a boolean predicate associated with them, and
141 /// the predicate must always be checked each time this function returns to
142 /// protect against spurious wakeups.
143 ///
144 /// # Errors
145 ///
146 /// This function will return an error if the mutex being waited on is
147 /// poisoned when this thread re-acquires the lock. For more information,
148 /// see information about [poisoning] on the [`Mutex`] type.
149 ///
150 /// # Panics
151 ///
152 /// This function may [`panic!`] if it is used with more than one mutex
153 /// over time.
154 ///
155 /// [`notify_one`]: Self::notify_one
156 /// [`notify_all`]: Self::notify_all
157 /// [poisoning]: super::Mutex#poisoning
158 /// [`Mutex`]: super::Mutex
159 ///
160 /// # Examples
161 ///
162 /// ```
163 /// use std::sync::{Arc, Mutex, Condvar};
164 /// use std::thread;
165 ///
166 /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
167 /// let pair2 = Arc::clone(&pair);
168 ///
169 /// thread::spawn(move|| {
170 /// let (lock, cvar) = &*pair2;
171 /// let mut started = lock.lock().unwrap();
172 /// *started = true;
173 /// // We notify the condvar that the value has changed.
174 /// cvar.notify_one();
175 /// });
176 ///
177 /// // Wait for the thread to start up.
178 /// let (lock, cvar) = &*pair;
179 /// let mut started = lock.lock().unwrap();
180 /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
181 /// while !*started {
182 /// started = cvar.wait(started).unwrap();
183 /// }
184 /// ```
185 #[stable(feature = "rust1", since = "1.0.0")]
186 pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> LockResult<MutexGuard<'a, T>> {
187 let poisoned = unsafe {
188 let lock = mutex::guard_lock(&guard);
189 self.inner.wait(lock);
190 mutex::guard_poison(&guard).get()
191 };
192 if poisoned { Err(PoisonError::new(guard)) } else { Ok(guard) }
193 }
194
195 /// Blocks the current thread until this condition variable receives a
196 /// notification and the provided condition is false.
197 ///
198 /// This function will atomically unlock the mutex specified (represented by
199 /// `guard`) and block the current thread. This means that any calls
200 /// to [`notify_one`] or [`notify_all`] which happen logically after the
201 /// mutex is unlocked are candidates to wake this thread up. When this
202 /// function call returns, the lock specified will have been re-acquired.
203 ///
204 /// # Errors
205 ///
206 /// This function will return an error if the mutex being waited on is
207 /// poisoned when this thread re-acquires the lock. For more information,
208 /// see information about [poisoning] on the [`Mutex`] type.
209 ///
210 /// [`notify_one`]: Self::notify_one
211 /// [`notify_all`]: Self::notify_all
212 /// [poisoning]: super::Mutex#poisoning
213 /// [`Mutex`]: super::Mutex
214 ///
215 /// # Examples
216 ///
217 /// ```
218 /// use std::sync::{Arc, Mutex, Condvar};
219 /// use std::thread;
220 ///
221 /// let pair = Arc::new((Mutex::new(true), Condvar::new()));
222 /// let pair2 = Arc::clone(&pair);
223 ///
224 /// thread::spawn(move|| {
225 /// let (lock, cvar) = &*pair2;
226 /// let mut pending = lock.lock().unwrap();
227 /// *pending = false;
228 /// // We notify the condvar that the value has changed.
229 /// cvar.notify_one();
230 /// });
231 ///
232 /// // Wait for the thread to start up.
233 /// let (lock, cvar) = &*pair;
234 /// // As long as the value inside the `Mutex<bool>` is `true`, we wait.
235 /// let _guard = cvar.wait_while(lock.lock().unwrap(), |pending| { *pending }).unwrap();
236 /// ```
237 #[stable(feature = "wait_until", since = "1.42.0")]
238 pub fn wait_while<'a, T, F>(
239 &self,
240 mut guard: MutexGuard<'a, T>,
241 mut condition: F,
242 ) -> LockResult<MutexGuard<'a, T>>
243 where
244 F: FnMut(&mut T) -> bool,
245 {
246 while condition(&mut *guard) {
247 guard = self.wait(guard)?;
248 }
249 Ok(guard)
250 }
251
252 /// Waits on this condition variable for a notification, timing out after a
253 /// specified duration.
254 ///
255 /// The semantics of this function are equivalent to [`wait`]
256 /// except that the thread will be blocked for roughly no longer
257 /// than `ms` milliseconds. This method should not be used for
258 /// precise timing due to anomalies such as preemption or platform
259 /// differences that might not cause the maximum amount of time
260 /// waited to be precisely `ms`.
261 ///
262 /// Note that the best effort is made to ensure that the time waited is
263 /// measured with a monotonic clock, and not affected by the changes made to
264 /// the system time.
265 ///
266 /// The returned boolean is `false` only if the timeout is known
267 /// to have elapsed.
268 ///
269 /// Like [`wait`], the lock specified will be re-acquired when this function
270 /// returns, regardless of whether the timeout elapsed or not.
271 ///
272 /// [`wait`]: Self::wait
273 ///
274 /// # Examples
275 ///
276 /// ```
277 /// use std::sync::{Arc, Mutex, Condvar};
278 /// use std::thread;
279 ///
280 /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
281 /// let pair2 = Arc::clone(&pair);
282 ///
283 /// thread::spawn(move|| {
284 /// let (lock, cvar) = &*pair2;
285 /// let mut started = lock.lock().unwrap();
286 /// *started = true;
287 /// // We notify the condvar that the value has changed.
288 /// cvar.notify_one();
289 /// });
290 ///
291 /// // Wait for the thread to start up.
292 /// let (lock, cvar) = &*pair;
293 /// let mut started = lock.lock().unwrap();
294 /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
295 /// loop {
296 /// let result = cvar.wait_timeout_ms(started, 10).unwrap();
297 /// // 10 milliseconds have passed, or maybe the value changed!
298 /// started = result.0;
299 /// if *started == true {
300 /// // We received the notification and the value has been updated, we can leave.
301 /// break
302 /// }
303 /// }
304 /// ```
305 #[stable(feature = "rust1", since = "1.0.0")]
306 #[deprecated(since = "1.6.0", note = "replaced by `std::sync::Condvar::wait_timeout`")]
307 pub fn wait_timeout_ms<'a, T>(
308 &self,
309 guard: MutexGuard<'a, T>,
310 ms: u32,
311 ) -> LockResult<(MutexGuard<'a, T>, bool)> {
312 let res = self.wait_timeout(guard, Duration::from_millis(ms as u64));
313 poison::map_result(res, |(a, b)| (a, !b.timed_out()))
314 }
315
316 /// Waits on this condition variable for a notification, timing out after a
317 /// specified duration.
318 ///
319 /// The semantics of this function are equivalent to [`wait`] except that
320 /// the thread will be blocked for roughly no longer than `dur`. This
321 /// method should not be used for precise timing due to anomalies such as
322 /// preemption or platform differences that might not cause the maximum
323 /// amount of time waited to be precisely `dur`.
324 ///
325 /// Note that the best effort is made to ensure that the time waited is
326 /// measured with a monotonic clock, and not affected by the changes made to
327 /// the system time. This function is susceptible to spurious wakeups.
328 /// Condition variables normally have a boolean predicate associated with
329 /// them, and the predicate must always be checked each time this function
330 /// returns to protect against spurious wakeups. Additionally, it is
331 /// typically desirable for the timeout to not exceed some duration in
332 /// spite of spurious wakes, thus the sleep-duration is decremented by the
333 /// amount slept. Alternatively, use the `wait_timeout_while` method
334 /// to wait with a timeout while a predicate is true.
335 ///
336 /// The returned [`WaitTimeoutResult`] value indicates if the timeout is
337 /// known to have elapsed.
338 ///
339 /// Like [`wait`], the lock specified will be re-acquired when this function
340 /// returns, regardless of whether the timeout elapsed or not.
341 ///
342 /// [`wait`]: Self::wait
343 /// [`wait_timeout_while`]: Self::wait_timeout_while
344 ///
345 /// # Examples
346 ///
347 /// ```
348 /// use std::sync::{Arc, Mutex, Condvar};
349 /// use std::thread;
350 /// use std::time::Duration;
351 ///
352 /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
353 /// let pair2 = Arc::clone(&pair);
354 ///
355 /// thread::spawn(move|| {
356 /// let (lock, cvar) = &*pair2;
357 /// let mut started = lock.lock().unwrap();
358 /// *started = true;
359 /// // We notify the condvar that the value has changed.
360 /// cvar.notify_one();
361 /// });
362 ///
363 /// // wait for the thread to start up
364 /// let (lock, cvar) = &*pair;
365 /// let mut started = lock.lock().unwrap();
366 /// // as long as the value inside the `Mutex<bool>` is `false`, we wait
367 /// loop {
368 /// let result = cvar.wait_timeout(started, Duration::from_millis(10)).unwrap();
369 /// // 10 milliseconds have passed, or maybe the value changed!
370 /// started = result.0;
371 /// if *started == true {
372 /// // We received the notification and the value has been updated, we can leave.
373 /// break
374 /// }
375 /// }
376 /// ```
377 #[stable(feature = "wait_timeout", since = "1.5.0")]
378 pub fn wait_timeout<'a, T>(
379 &self,
380 guard: MutexGuard<'a, T>,
381 dur: Duration,
382 ) -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)> {
383 let (poisoned, result) = unsafe {
384 let lock = mutex::guard_lock(&guard);
385 let success = self.inner.wait_timeout(lock, dur);
386 (mutex::guard_poison(&guard).get(), WaitTimeoutResult(!success))
387 };
388 if poisoned { Err(PoisonError::new((guard, result))) } else { Ok((guard, result)) }
389 }
390
391 /// Waits on this condition variable for a notification, timing out after a
392 /// specified duration.
393 ///
394 /// The semantics of this function are equivalent to [`wait_while`] except
395 /// that the thread will be blocked for roughly no longer than `dur`. This
396 /// method should not be used for precise timing due to anomalies such as
397 /// preemption or platform differences that might not cause the maximum
398 /// amount of time waited to be precisely `dur`.
399 ///
400 /// Note that the best effort is made to ensure that the time waited is
401 /// measured with a monotonic clock, and not affected by the changes made to
402 /// the system time.
403 ///
404 /// The returned [`WaitTimeoutResult`] value indicates if the timeout is
405 /// known to have elapsed without the condition being met.
406 ///
407 /// Like [`wait_while`], the lock specified will be re-acquired when this
408 /// function returns, regardless of whether the timeout elapsed or not.
409 ///
410 /// [`wait_while`]: Self::wait_while
411 /// [`wait_timeout`]: Self::wait_timeout
412 ///
413 /// # Examples
414 ///
415 /// ```
416 /// use std::sync::{Arc, Mutex, Condvar};
417 /// use std::thread;
418 /// use std::time::Duration;
419 ///
420 /// let pair = Arc::new((Mutex::new(true), Condvar::new()));
421 /// let pair2 = Arc::clone(&pair);
422 ///
423 /// thread::spawn(move|| {
424 /// let (lock, cvar) = &*pair2;
425 /// let mut pending = lock.lock().unwrap();
426 /// *pending = false;
427 /// // We notify the condvar that the value has changed.
428 /// cvar.notify_one();
429 /// });
430 ///
431 /// // wait for the thread to start up
432 /// let (lock, cvar) = &*pair;
433 /// let result = cvar.wait_timeout_while(
434 /// lock.lock().unwrap(),
435 /// Duration::from_millis(100),
436 /// |&mut pending| pending,
437 /// ).unwrap();
438 /// if result.1.timed_out() {
439 /// // timed-out without the condition ever evaluating to false.
440 /// }
441 /// // access the locked mutex via result.0
442 /// ```
443 #[stable(feature = "wait_timeout_until", since = "1.42.0")]
444 pub fn wait_timeout_while<'a, T, F>(
445 &self,
446 mut guard: MutexGuard<'a, T>,
447 dur: Duration,
448 mut condition: F,
449 ) -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)>
450 where
451 F: FnMut(&mut T) -> bool,
452 {
453 let start = Instant::now();
454 loop {
455 if !condition(&mut *guard) {
456 return Ok((guard, WaitTimeoutResult(false)));
457 }
458 let timeout = match dur.checked_sub(start.elapsed()) {
459 Some(timeout) => timeout,
460 None => return Ok((guard, WaitTimeoutResult(true))),
461 };
462 guard = self.wait_timeout(guard, timeout)?.0;
463 }
464 }
465
466 /// Wakes up one blocked thread on this condvar.
467 ///
468 /// If there is a blocked thread on this condition variable, then it will
469 /// be woken up from its call to [`wait`] or [`wait_timeout`]. Calls to
470 /// `notify_one` are not buffered in any way.
471 ///
472 /// To wake up all threads, see [`notify_all`].
473 ///
474 /// [`wait`]: Self::wait
475 /// [`wait_timeout`]: Self::wait_timeout
476 /// [`notify_all`]: Self::notify_all
477 ///
478 /// # Examples
479 ///
480 /// ```
481 /// use std::sync::{Arc, Mutex, Condvar};
482 /// use std::thread;
483 ///
484 /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
485 /// let pair2 = Arc::clone(&pair);
486 ///
487 /// thread::spawn(move|| {
488 /// let (lock, cvar) = &*pair2;
489 /// let mut started = lock.lock().unwrap();
490 /// *started = true;
491 /// // We notify the condvar that the value has changed.
492 /// cvar.notify_one();
493 /// });
494 ///
495 /// // Wait for the thread to start up.
496 /// let (lock, cvar) = &*pair;
497 /// let mut started = lock.lock().unwrap();
498 /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
499 /// while !*started {
500 /// started = cvar.wait(started).unwrap();
501 /// }
502 /// ```
503 #[stable(feature = "rust1", since = "1.0.0")]
504 pub fn notify_one(&self) {
505 self.inner.notify_one()
506 }
507
508 /// Wakes up all blocked threads on this condvar.
509 ///
510 /// This method will ensure that any current waiters on the condition
511 /// variable are awoken. Calls to `notify_all()` are not buffered in any
512 /// way.
513 ///
514 /// To wake up only one thread, see [`notify_one`].
515 ///
516 /// [`notify_one`]: Self::notify_one
517 ///
518 /// # Examples
519 ///
520 /// ```
521 /// use std::sync::{Arc, Mutex, Condvar};
522 /// use std::thread;
523 ///
524 /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
525 /// let pair2 = Arc::clone(&pair);
526 ///
527 /// thread::spawn(move|| {
528 /// let (lock, cvar) = &*pair2;
529 /// let mut started = lock.lock().unwrap();
530 /// *started = true;
531 /// // We notify the condvar that the value has changed.
532 /// cvar.notify_all();
533 /// });
534 ///
535 /// // Wait for the thread to start up.
536 /// let (lock, cvar) = &*pair;
537 /// let mut started = lock.lock().unwrap();
538 /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
539 /// while !*started {
540 /// started = cvar.wait(started).unwrap();
541 /// }
542 /// ```
543 #[stable(feature = "rust1", since = "1.0.0")]
544 pub fn notify_all(&self) {
545 self.inner.notify_all()
546 }
547}
548
549#[stable(feature = "std_debug", since = "1.16.0")]
550impl fmt::Debug for Condvar {
551 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
552 f.debug_struct(name:"Condvar").finish_non_exhaustive()
553 }
554}
555
556#[stable(feature = "condvar_default", since = "1.10.0")]
557impl Default for Condvar {
558 /// Creates a `Condvar` which is ready to be waited on and notified.
559 fn default() -> Condvar {
560 Condvar::new()
561 }
562}
563