Hello World
use std::sync::{Arc, Mutex, Condvar};
use std::thread;
use std::time::Duration;
fn main() {
let pair = Arc::new((Mutex::new(true), Condvar::new()));
let pair_clone = pair.clone();
thread::spawn(move || {
let (lock, cvar) = &*pair_clone;
cvar.notify_all(); // spurious wakeup example
println!("[awaited] doing expensive computation");
thread::sleep(Duration::from_millis(1000));
println!("[awaited] done");
let mut pending = lock.lock().unwrap();
println!("[awaited] got lock");
*pending = false;
println!("[awaited] notifying");
cvar.notify_all();
});
let (lock, cvar) = &*pair;
// As long as the value inside the `Mutex<bool>` is `true`, we wait.
let _guard = cvar.wait_while(lock.lock().unwrap(), |pending| {
println!("[waiter] checking condition {}", *pending);
*pending
}).unwrap();
println!("[waiter] current mutex content {}", *_guard);
println!("[waiter] done");
}
Multiple waiters
use std::sync::{Arc, Mutex, Condvar};
use std::thread;
use std::time::Duration;
use std::thread::JoinHandle;
fn main() {
const N:i32 = 5;
let pair = Arc::new((Mutex::new(true), Condvar::new()));
let pair_clone = pair.clone();
let awaited = thread::spawn(move || {
loop {
let (lock, cvar) = &*pair_clone;
println!("[awaited] doing expensive computation");
thread::sleep(Duration::from_millis(1000));
println!("[awaited] done");
let mut pending = lock.lock().unwrap();
println!("[awaited] got lock");
*pending = false;
println!("[awaited] notifying");
// play with notify_one
cvar.notify_all();
}
});
let waiters:Vec<JoinHandle<()>> = (1..N).map(|i| {
let pair_clone_waiter = pair.clone();
thread::spawn(move || {
loop {
let (lock, cvar) = &*pair_clone_waiter;
let mut _guard = cvar.wait_while(lock.lock().unwrap(), |pending| {
println!("[waiter {}] checking condition {}", i, *pending);
*pending
}).unwrap();
println!("[waiter {}] woke up", i);
thread::sleep(Duration::from_millis(1000));
(*_guard) = true;
println!("[waiter {}] done", i);
}
})
}).collect();
let _:Vec<()> = waiters.into_iter()
.flat_map(|x| x.join())
.collect();
awaited.join().unwrap();
}
- A medida que el productor lo ponga en False, se despiertan todos y uno lo consume.
- El que lo tomó, trabaja y deja el lugar.
- Si se que solo uno va a poder trabajar, hago notify_one() en vez de notify_all()
Esperar por dos Cond_vars
extern crate rand;
use std::sync::{Arc, Mutex, Condvar};
use std::thread;
use std::time::Duration;
use rand::{thread_rng, Rng};
fn main() {
#[derive(Debug)]
struct State {
pending_first: bool,
pending_second: bool
}
let pair = Arc::new((Mutex::new(State { pending_first: true, pending_second: true} ), Condvar::new()));
let pair_clone = pair.clone();
thread::spawn(move || {
let (lock, cvar) = &*pair_clone;
println!("[awaited 1] doing expensive computation");
thread::sleep(Duration::from_millis(thread_rng().gen_range(500, 1500)));
println!("[awaited 1] done");
let mut state = lock.lock().unwrap();
println!("[awaited 1] got lock");
state.pending_first = false;
println!("[awaited 1] notifying");
cvar.notify_all();
});
let pair_clone2 = pair.clone();
thread::spawn(move || {
let (lock, cvar) = &*pair_clone2;
println!("[awaited 2] doing expensive computation");
thread::sleep(Duration::from_millis(thread_rng().gen_range(500, 1500)));
println!("[awaited 2] done");
let mut state = lock.lock().unwrap();
println!("[awaited 2] got lock");
state.pending_second = false;
println!("[awaited 2] notifying");
cvar.notify_all();
});
let (lock, cvar) = &*pair;
// As long as the value inside the `Mutex<bool>` is `true`, we wait.
let _guard = cvar.wait_while(lock.lock().unwrap(), |pending| {
println!("[waiter] checking condition {:?}", *pending);
pending.pending_first || pending.pending_second
}).unwrap();
println!("[waiter] done");
}