From ad728a0a633f82c881c29788d99ca81f66155751 Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 17 May 2024 16:02:06 -0300 Subject: [PATCH] Implement wait_while for condvar --- src/sync/condvar.rs | 17 +++++++++++++++++ tests/condvar.rs | 22 ++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/sync/condvar.rs b/src/sync/condvar.rs index b173e4e5..205d5189 100644 --- a/src/sync/condvar.rs +++ b/src/sync/condvar.rs @@ -39,6 +39,23 @@ impl Condvar { Ok(guard) } + /// Blocks the current thread until this condition variable receives a notification and the + /// provided condition is false. + pub fn wait_while<'a, T, F>( + &self, + mut guard: MutexGuard<'a, T>, + mut condition: F, + ) -> LockResult> + where + F: FnMut(&mut T) -> bool, + { + while condition(&mut *guard) { + guard = self.wait(guard)?; + } + + Ok(guard) + } + /// Waits on this condition variable for a notification, timing out after a /// specified duration. pub fn wait_timeout<'a, T>( diff --git a/tests/condvar.rs b/tests/condvar.rs index 6f3a4823..03d1ad9f 100644 --- a/tests/condvar.rs +++ b/tests/condvar.rs @@ -80,3 +80,25 @@ impl Inc { self.condvar.notify_all(); } } + +#[test] +fn wait_while() { + loom::model(|| { + let pair = Arc::new((Mutex::new(true), Condvar::new())); + let pair_2 = Arc::clone(&pair); + + thread::spawn(move || { + let (lock, cvar) = &*pair_2; + let mut pending = lock.lock().unwrap(); + *pending = false; + cvar.notify_one(); + }); + + let (lock, cvar) = &*pair; + let guard = cvar + .wait_while(lock.lock().unwrap(), |pending| *pending) + .unwrap(); + + assert_eq!(*guard, false); + }); +}