std/sync/poison/
condvar.rs

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