1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2018 The ChromiumOS Authors 2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file. 4*bb4ee6a4SAndroid Build Coastguard Worker 5*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt; 6*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt::Debug; 7*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Condvar as StdCondvar; 8*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::MutexGuard; 9*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::WaitTimeoutResult; 10*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration; 11*bb4ee6a4SAndroid Build Coastguard Worker 12*bb4ee6a4SAndroid Build Coastguard Worker static CONDVAR_POISONED: &str = "condvar is poisoned"; 13*bb4ee6a4SAndroid Build Coastguard Worker 14*bb4ee6a4SAndroid Build Coastguard Worker /// A Condition Variable. 15*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Default)] 16*bb4ee6a4SAndroid Build Coastguard Worker pub struct Condvar { 17*bb4ee6a4SAndroid Build Coastguard Worker std: StdCondvar, 18*bb4ee6a4SAndroid Build Coastguard Worker } 19*bb4ee6a4SAndroid Build Coastguard Worker 20*bb4ee6a4SAndroid Build Coastguard Worker impl Condvar { 21*bb4ee6a4SAndroid Build Coastguard Worker /// Creates a new condvar that is ready to be waited on. new() -> Condvar22*bb4ee6a4SAndroid Build Coastguard Worker pub const fn new() -> Condvar { 23*bb4ee6a4SAndroid Build Coastguard Worker Condvar { 24*bb4ee6a4SAndroid Build Coastguard Worker std: StdCondvar::new(), 25*bb4ee6a4SAndroid Build Coastguard Worker } 26*bb4ee6a4SAndroid Build Coastguard Worker } 27*bb4ee6a4SAndroid Build Coastguard Worker 28*bb4ee6a4SAndroid Build Coastguard Worker /// Waits on a condvar, blocking the current thread until it is notified. wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> MutexGuard<'a, T>29*bb4ee6a4SAndroid Build Coastguard Worker pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> MutexGuard<'a, T> { 30*bb4ee6a4SAndroid Build Coastguard Worker self.std.wait(guard).expect(CONDVAR_POISONED) 31*bb4ee6a4SAndroid Build Coastguard Worker } 32*bb4ee6a4SAndroid Build Coastguard Worker 33*bb4ee6a4SAndroid Build Coastguard Worker /// Blocks the current thread until this condition variable receives a notification and the 34*bb4ee6a4SAndroid Build Coastguard Worker /// provided condition is false. wait_while<'a, T, F>(&self, guard: MutexGuard<'a, T>, condition: F) -> MutexGuard<'a, T> where F: FnMut(&mut T) -> bool,35*bb4ee6a4SAndroid Build Coastguard Worker pub fn wait_while<'a, T, F>(&self, guard: MutexGuard<'a, T>, condition: F) -> MutexGuard<'a, T> 36*bb4ee6a4SAndroid Build Coastguard Worker where 37*bb4ee6a4SAndroid Build Coastguard Worker F: FnMut(&mut T) -> bool, 38*bb4ee6a4SAndroid Build Coastguard Worker { 39*bb4ee6a4SAndroid Build Coastguard Worker self.std 40*bb4ee6a4SAndroid Build Coastguard Worker .wait_while(guard, condition) 41*bb4ee6a4SAndroid Build Coastguard Worker .expect(CONDVAR_POISONED) 42*bb4ee6a4SAndroid Build Coastguard Worker } 43*bb4ee6a4SAndroid Build Coastguard Worker 44*bb4ee6a4SAndroid Build Coastguard Worker /// Waits on a condvar, blocking the current thread until it is notified 45*bb4ee6a4SAndroid Build Coastguard Worker /// or the specified duration has elapsed. wait_timeout<'a, T>( &self, guard: MutexGuard<'a, T>, dur: Duration, ) -> (MutexGuard<'a, T>, WaitTimeoutResult)46*bb4ee6a4SAndroid Build Coastguard Worker pub fn wait_timeout<'a, T>( 47*bb4ee6a4SAndroid Build Coastguard Worker &self, 48*bb4ee6a4SAndroid Build Coastguard Worker guard: MutexGuard<'a, T>, 49*bb4ee6a4SAndroid Build Coastguard Worker dur: Duration, 50*bb4ee6a4SAndroid Build Coastguard Worker ) -> (MutexGuard<'a, T>, WaitTimeoutResult) { 51*bb4ee6a4SAndroid Build Coastguard Worker self.std.wait_timeout(guard, dur).expect(CONDVAR_POISONED) 52*bb4ee6a4SAndroid Build Coastguard Worker } 53*bb4ee6a4SAndroid Build Coastguard Worker 54*bb4ee6a4SAndroid Build Coastguard Worker /// Waits on this condition variable for a notification, timing out after a specified duration. wait_timeout_while<'a, T, F>( &self, guard: MutexGuard<'a, T>, dur: Duration, condition: F, ) -> (MutexGuard<'a, T>, WaitTimeoutResult) where F: FnMut(&mut T) -> bool,55*bb4ee6a4SAndroid Build Coastguard Worker pub fn wait_timeout_while<'a, T, F>( 56*bb4ee6a4SAndroid Build Coastguard Worker &self, 57*bb4ee6a4SAndroid Build Coastguard Worker guard: MutexGuard<'a, T>, 58*bb4ee6a4SAndroid Build Coastguard Worker dur: Duration, 59*bb4ee6a4SAndroid Build Coastguard Worker condition: F, 60*bb4ee6a4SAndroid Build Coastguard Worker ) -> (MutexGuard<'a, T>, WaitTimeoutResult) 61*bb4ee6a4SAndroid Build Coastguard Worker where 62*bb4ee6a4SAndroid Build Coastguard Worker F: FnMut(&mut T) -> bool, 63*bb4ee6a4SAndroid Build Coastguard Worker { 64*bb4ee6a4SAndroid Build Coastguard Worker self.std 65*bb4ee6a4SAndroid Build Coastguard Worker .wait_timeout_while(guard, dur, condition) 66*bb4ee6a4SAndroid Build Coastguard Worker .expect(CONDVAR_POISONED) 67*bb4ee6a4SAndroid Build Coastguard Worker } 68*bb4ee6a4SAndroid Build Coastguard Worker 69*bb4ee6a4SAndroid Build Coastguard Worker /// Notifies one thread blocked by this condvar. notify_one(&self)70*bb4ee6a4SAndroid Build Coastguard Worker pub fn notify_one(&self) { 71*bb4ee6a4SAndroid Build Coastguard Worker self.std.notify_one(); 72*bb4ee6a4SAndroid Build Coastguard Worker } 73*bb4ee6a4SAndroid Build Coastguard Worker 74*bb4ee6a4SAndroid Build Coastguard Worker /// Notifies all threads blocked by this condvar. notify_all(&self)75*bb4ee6a4SAndroid Build Coastguard Worker pub fn notify_all(&self) { 76*bb4ee6a4SAndroid Build Coastguard Worker self.std.notify_all(); 77*bb4ee6a4SAndroid Build Coastguard Worker } 78*bb4ee6a4SAndroid Build Coastguard Worker } 79*bb4ee6a4SAndroid Build Coastguard Worker 80*bb4ee6a4SAndroid Build Coastguard Worker impl Debug for Condvar { fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result81*bb4ee6a4SAndroid Build Coastguard Worker fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 82*bb4ee6a4SAndroid Build Coastguard Worker Debug::fmt(&self.std, formatter) 83*bb4ee6a4SAndroid Build Coastguard Worker } 84*bb4ee6a4SAndroid Build Coastguard Worker } 85