I want to wait a value that is protected by an RwLock
until it satisfies a certain condition, after some searching, I have found the following implementation: https://github.com/Amanieu/parking_lot/issues/165#issuecomment-515991706, but the original comment doesn’t say anything about how to call notify_all
. It suspect I have to lock the associated Mutex
when calling notify_all
, otherwise the program could hang. See this example (playground link):
use parking_lot::{Condvar, Mutex, RwLock, RwLockReadGuard};
use std::thread;
struct RwLockCondvar {
condvar: Condvar,
mutex: Mutex<()>,
}
impl RwLockCondvar {
fn wait<T>(&self, read_guard: &mut RwLockReadGuard<'_, T>) {
let guard = self.mutex.lock();
RwLockReadGuard::unlocked(read_guard, || {
let mut guard = guard;
self.condvar.wait(&mut guard);
});
}
fn notify_all(&self) {
// It seems this locking is necessary.
let _guard = self.mutex.lock();
self.condvar.notify_all();
}
}
fn main() {
let flag = RwLock::new(false);
let condvar = RwLockCondvar {
condvar: Condvar::new(),
mutex: Mutex::new(()),
};
thread::scope(|scope| {
for i in 0..1000 {
println!("Iteration = {i}");
*flag.write() = false;
// Wait `flag` to become `true`.
let thread_1 = scope.spawn(|| {
let mut guard = flag.read();
while !*guard {
condvar.wait(&mut guard);
}
});
// Set `flag` to `true` and notify.
let thread_2 = scope.spawn(|| {
*flag.write() = true;
condvar.notify_all();
});
thread_1.join().unwrap();
thread_2.join().unwrap();
}
});
println!("Done");
}
Is this a correct implementation of a Condvar
on RwLock
?