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