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. Additionally, it is
273    /// typically desirable for the timeout to not exceed some duration in
274    /// spite of spurious wakes, thus the sleep-duration is decremented by the
275    /// amount slept. Alternatively, use the `wait_timeout_while` method
276    /// to wait with a timeout while a predicate is true.
277    ///
278    /// The returned [`WaitTimeoutResult`] value indicates if the timeout is
279    /// known to have elapsed.
280    ///
281    /// Like [`wait`], the lock specified will be re-acquired when this function
282    /// returns, regardless of whether the timeout elapsed or not.
283    ///
284    /// [`wait`]: Self::wait
285    /// [`wait_timeout_while`]: Self::wait_timeout_while
286    ///
287    /// # Examples
288    ///
289    /// ```
290    /// use std::sync::{Arc, Mutex, Condvar};
291    /// use std::thread;
292    /// use std::time::Duration;
293    ///
294    /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
295    /// let pair2 = Arc::clone(&pair);
296    ///
297    /// thread::spawn(move || {
298    ///     let (lock, cvar) = &*pair2;
299    ///     let mut started = lock.lock().unwrap();
300    ///     *started = true;
301    ///     // We notify the condvar that the value has changed.
302    ///     cvar.notify_one();
303    /// });
304    ///
305    /// // wait for the thread to start up
306    /// let (lock, cvar) = &*pair;
307    /// let mut started = lock.lock().unwrap();
308    /// // as long as the value inside the `Mutex<bool>` is `false`, we wait
309    /// loop {
310    ///     let result = cvar.wait_timeout(started, Duration::from_millis(10)).unwrap();
311    ///     // 10 milliseconds have passed, or maybe the value changed!
312    ///     started = result.0;
313    ///     if *started == true {
314    ///         // We received the notification and the value has been updated, we can leave.
315    ///         break
316    ///     }
317    /// }
318    /// ```
319    #[stable(feature = "wait_timeout", since = "1.5.0")]
320    pub fn wait_timeout<'a, T>(
321        &self,
322        guard: MutexGuard<'a, T>,
323        dur: Duration,
324    ) -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)> {
325        let (poisoned, result) = unsafe {
326            let lock = mutex::guard_lock(&guard);
327            let success = self.inner.wait_timeout(lock, dur);
328            (mutex::guard_poison(&guard).get(), WaitTimeoutResult(!success))
329        };
330        if poisoned { Err(PoisonError::new((guard, result))) } else { Ok((guard, result)) }
331    }
332
333    /// Waits on this condition variable for a notification, timing out after a
334    /// specified duration.
335    ///
336    /// The semantics of this function are equivalent to [`wait_while`] except
337    /// that the thread will be blocked for roughly no longer than `dur`. This
338    /// method should not be used for precise timing due to anomalies such as
339    /// preemption or platform differences that might not cause the maximum
340    /// amount of time waited to be precisely `dur`.
341    ///
342    /// Note that the best effort is made to ensure that the time waited is
343    /// measured with a monotonic clock, and not affected by the changes made to
344    /// the system time.
345    ///
346    /// The returned [`WaitTimeoutResult`] value indicates if the timeout is
347    /// known to have elapsed without the condition being met.
348    ///
349    /// Like [`wait_while`], the lock specified will be re-acquired when this
350    /// function returns, regardless of whether the timeout elapsed or not.
351    ///
352    /// [`wait_while`]: Self::wait_while
353    /// [`wait_timeout`]: Self::wait_timeout
354    ///
355    /// # Examples
356    ///
357    /// ```
358    /// use std::sync::{Arc, Mutex, Condvar};
359    /// use std::thread;
360    /// use std::time::Duration;
361    ///
362    /// let pair = Arc::new((Mutex::new(true), Condvar::new()));
363    /// let pair2 = Arc::clone(&pair);
364    ///
365    /// thread::spawn(move || {
366    ///     let (lock, cvar) = &*pair2;
367    ///     let mut pending = lock.lock().unwrap();
368    ///     *pending = false;
369    ///     // We notify the condvar that the value has changed.
370    ///     cvar.notify_one();
371    /// });
372    ///
373    /// // wait for the thread to start up
374    /// let (lock, cvar) = &*pair;
375    /// let result = cvar.wait_timeout_while(
376    ///     lock.lock().unwrap(),
377    ///     Duration::from_millis(100),
378    ///     |&mut pending| pending,
379    /// ).unwrap();
380    /// if result.1.timed_out() {
381    ///     // timed-out without the condition ever evaluating to false.
382    /// }
383    /// // access the locked mutex via result.0
384    /// ```
385    #[stable(feature = "wait_timeout_until", since = "1.42.0")]
386    pub fn wait_timeout_while<'a, T, F>(
387        &self,
388        mut guard: MutexGuard<'a, T>,
389        dur: Duration,
390        mut condition: F,
391    ) -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)>
392    where
393        F: FnMut(&mut T) -> bool,
394    {
395        let start = Instant::now();
396        loop {
397            if !condition(&mut *guard) {
398                return Ok((guard, WaitTimeoutResult(false)));
399            }
400            let timeout = match dur.checked_sub(start.elapsed()) {
401                Some(timeout) => timeout,
402                None => return Ok((guard, WaitTimeoutResult(true))),
403            };
404            guard = self.wait_timeout(guard, timeout)?.0;
405        }
406    }
407
408    /// Wakes up one blocked thread on this condvar.
409    ///
410    /// If there is a blocked thread on this condition variable, then it will
411    /// be woken up from its call to [`wait`] or [`wait_timeout`]. Calls to
412    /// `notify_one` are not buffered in any way.
413    ///
414    /// To wake up all threads, see [`notify_all`].
415    ///
416    /// [`wait`]: Self::wait
417    /// [`wait_timeout`]: Self::wait_timeout
418    /// [`notify_all`]: Self::notify_all
419    ///
420    /// # Examples
421    ///
422    /// ```
423    /// use std::sync::{Arc, Mutex, Condvar};
424    /// use std::thread;
425    ///
426    /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
427    /// let pair2 = Arc::clone(&pair);
428    ///
429    /// thread::spawn(move || {
430    ///     let (lock, cvar) = &*pair2;
431    ///     let mut started = lock.lock().unwrap();
432    ///     *started = true;
433    ///     // We notify the condvar that the value has changed.
434    ///     cvar.notify_one();
435    /// });
436    ///
437    /// // Wait for the thread to start up.
438    /// let (lock, cvar) = &*pair;
439    /// let mut started = lock.lock().unwrap();
440    /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
441    /// while !*started {
442    ///     started = cvar.wait(started).unwrap();
443    /// }
444    /// ```
445    #[stable(feature = "rust1", since = "1.0.0")]
446    pub fn notify_one(&self) {
447        self.inner.notify_one()
448    }
449
450    /// Wakes up all blocked threads on this condvar.
451    ///
452    /// This method will ensure that any current waiters on the condition
453    /// variable are awoken. Calls to `notify_all()` are not buffered in any
454    /// way.
455    ///
456    /// To wake up only one thread, see [`notify_one`].
457    ///
458    /// [`notify_one`]: Self::notify_one
459    ///
460    /// # Examples
461    ///
462    /// ```
463    /// use std::sync::{Arc, Mutex, Condvar};
464    /// use std::thread;
465    ///
466    /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
467    /// let pair2 = Arc::clone(&pair);
468    ///
469    /// thread::spawn(move || {
470    ///     let (lock, cvar) = &*pair2;
471    ///     let mut started = lock.lock().unwrap();
472    ///     *started = true;
473    ///     // We notify the condvar that the value has changed.
474    ///     cvar.notify_all();
475    /// });
476    ///
477    /// // Wait for the thread to start up.
478    /// let (lock, cvar) = &*pair;
479    /// let mut started = lock.lock().unwrap();
480    /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
481    /// while !*started {
482    ///     started = cvar.wait(started).unwrap();
483    /// }
484    /// ```
485    #[stable(feature = "rust1", since = "1.0.0")]
486    pub fn notify_all(&self) {
487        self.inner.notify_all()
488    }
489}
490
491#[stable(feature = "std_debug", since = "1.16.0")]
492impl fmt::Debug for Condvar {
493    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
494        f.debug_struct("Condvar").finish_non_exhaustive()
495    }
496}
497
498#[stable(feature = "condvar_default", since = "1.10.0")]
499impl Default for Condvar {
500    /// Creates a `Condvar` which is ready to be waited on and notified.
501    fn default() -> Condvar {
502        Condvar::new()
503    }
504}