5 use crate::sync::{Condvar, Mutex};
7 /// A barrier enables multiple threads to synchronize the beginning
8 /// of some computation.
13 /// use std::sync::{Arc, Barrier};
16 /// let mut handles = Vec::with_capacity(10);
17 /// let barrier = Arc::new(Barrier::new(10));
19 /// let c = barrier.clone();
20 /// // The same messages will be printed together.
21 /// // You will NOT see any interleaving.
22 /// handles.push(thread::spawn(move|| {
23 /// println!("before wait");
25 /// println!("after wait");
28 /// // Wait for other threads to finish.
29 /// for handle in handles {
30 /// handle.join().unwrap();
33 #[stable(feature = "rust1", since = "1.0.0")]
35 lock: Mutex<BarrierState>,
40 // The inner state of a double barrier
46 /// A `BarrierWaitResult` is returned by [`wait`] when all threads in the [`Barrier`]
47 /// have rendezvoused.
49 /// [`wait`]: struct.Barrier.html#method.wait
50 /// [`Barrier`]: struct.Barrier.html
55 /// use std::sync::Barrier;
57 /// let barrier = Barrier::new(1);
58 /// let barrier_wait_result = barrier.wait();
60 #[stable(feature = "rust1", since = "1.0.0")]
61 pub struct BarrierWaitResult(bool);
63 #[stable(feature = "std_debug", since = "1.16.0")]
64 impl fmt::Debug for Barrier {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 f.pad("Barrier { .. }")
71 /// Creates a new barrier that can block a given number of threads.
73 /// A barrier will block `n`-1 threads which call [`wait`] and then wake up
74 /// all threads at once when the `n`th thread calls [`wait`].
76 /// [`wait`]: #method.wait
81 /// use std::sync::Barrier;
83 /// let barrier = Barrier::new(10);
85 #[stable(feature = "rust1", since = "1.0.0")]
86 pub fn new(n: usize) -> Barrier {
88 lock: Mutex::new(BarrierState { count: 0, generation_id: 0 }),
94 /// Blocks the current thread until all threads have rendezvoused here.
96 /// Barriers are re-usable after all threads have rendezvoused once, and can
97 /// be used continuously.
99 /// A single (arbitrary) thread will receive a [`BarrierWaitResult`] that
100 /// returns `true` from [`is_leader`] when returning from this function, and
101 /// all other threads will receive a result that will return `false` from
104 /// [`BarrierWaitResult`]: struct.BarrierWaitResult.html
105 /// [`is_leader`]: struct.BarrierWaitResult.html#method.is_leader
110 /// use std::sync::{Arc, Barrier};
113 /// let mut handles = Vec::with_capacity(10);
114 /// let barrier = Arc::new(Barrier::new(10));
116 /// let c = barrier.clone();
117 /// // The same messages will be printed together.
118 /// // You will NOT see any interleaving.
119 /// handles.push(thread::spawn(move|| {
120 /// println!("before wait");
122 /// println!("after wait");
125 /// // Wait for other threads to finish.
126 /// for handle in handles {
127 /// handle.join().unwrap();
130 #[stable(feature = "rust1", since = "1.0.0")]
131 pub fn wait(&self) -> BarrierWaitResult {
132 let mut lock = self.lock.lock().unwrap();
133 let local_gen = lock.generation_id;
135 if lock.count < self.num_threads {
136 // We need a while loop to guard against spurious wakeups.
137 // https://en.wikipedia.org/wiki/Spurious_wakeup
138 while local_gen == lock.generation_id && lock.count < self.num_threads {
139 lock = self.cvar.wait(lock).unwrap();
141 BarrierWaitResult(false)
144 lock.generation_id = lock.generation_id.wrapping_add(1);
145 self.cvar.notify_all();
146 BarrierWaitResult(true)
151 #[stable(feature = "std_debug", since = "1.16.0")]
152 impl fmt::Debug for BarrierWaitResult {
153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154 f.debug_struct("BarrierWaitResult").field("is_leader", &self.is_leader()).finish()
158 impl BarrierWaitResult {
159 /// Returns `true` if this thread from [`wait`] is the "leader thread".
161 /// Only one thread will have `true` returned from their result, all other
162 /// threads will have `false` returned.
164 /// [`wait`]: struct.Barrier.html#method.wait
169 /// use std::sync::Barrier;
171 /// let barrier = Barrier::new(1);
172 /// let barrier_wait_result = barrier.wait();
173 /// println!("{:?}", barrier_wait_result.is_leader());
175 #[stable(feature = "rust1", since = "1.0.0")]
176 pub fn is_leader(&self) -> bool {