std/sync/poison/
condvar.rs

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