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::collections::BTreeMap; 6*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::drop; 7*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc; 8*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Weak; 9*bb4ee6a4SAndroid Build Coastguard Worker use std::thread; 10*bb4ee6a4SAndroid Build Coastguard Worker 11*bb4ee6a4SAndroid Build Coastguard Worker use base::error; 12*bb4ee6a4SAndroid Build Coastguard Worker use base::warn; 13*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor; 14*bb4ee6a4SAndroid Build Coastguard Worker use base::Descriptor; 15*bb4ee6a4SAndroid Build Coastguard Worker use base::Event; 16*bb4ee6a4SAndroid Build Coastguard Worker use base::EventType; 17*bb4ee6a4SAndroid Build Coastguard Worker use base::WaitContext; 18*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex; 19*bb4ee6a4SAndroid Build Coastguard Worker 20*bb4ee6a4SAndroid Build Coastguard Worker use super::error::Error; 21*bb4ee6a4SAndroid Build Coastguard Worker use super::error::Result; 22*bb4ee6a4SAndroid Build Coastguard Worker 23*bb4ee6a4SAndroid Build Coastguard Worker /// A fail handle will do the clean up when we cannot recover from some error. 24*bb4ee6a4SAndroid Build Coastguard Worker pub trait FailHandle: Send + Sync { 25*bb4ee6a4SAndroid Build Coastguard Worker /// Fail the code. fail(&self)26*bb4ee6a4SAndroid Build Coastguard Worker fn fail(&self); 27*bb4ee6a4SAndroid Build Coastguard Worker /// Returns true if already failed. failed(&self) -> bool28*bb4ee6a4SAndroid Build Coastguard Worker fn failed(&self) -> bool; 29*bb4ee6a4SAndroid Build Coastguard Worker } 30*bb4ee6a4SAndroid Build Coastguard Worker 31*bb4ee6a4SAndroid Build Coastguard Worker impl FailHandle for Option<Arc<dyn FailHandle>> { fail(&self)32*bb4ee6a4SAndroid Build Coastguard Worker fn fail(&self) { 33*bb4ee6a4SAndroid Build Coastguard Worker match self { 34*bb4ee6a4SAndroid Build Coastguard Worker Some(handle) => handle.fail(), 35*bb4ee6a4SAndroid Build Coastguard Worker None => error!("event loop trying to fail without a fail handle"), 36*bb4ee6a4SAndroid Build Coastguard Worker } 37*bb4ee6a4SAndroid Build Coastguard Worker } 38*bb4ee6a4SAndroid Build Coastguard Worker failed(&self) -> bool39*bb4ee6a4SAndroid Build Coastguard Worker fn failed(&self) -> bool { 40*bb4ee6a4SAndroid Build Coastguard Worker match self { 41*bb4ee6a4SAndroid Build Coastguard Worker Some(handle) => handle.failed(), 42*bb4ee6a4SAndroid Build Coastguard Worker None => false, 43*bb4ee6a4SAndroid Build Coastguard Worker } 44*bb4ee6a4SAndroid Build Coastguard Worker } 45*bb4ee6a4SAndroid Build Coastguard Worker } 46*bb4ee6a4SAndroid Build Coastguard Worker 47*bb4ee6a4SAndroid Build Coastguard Worker /// EventLoop is an event loop blocked on a set of fds. When a monitered events is triggered, 48*bb4ee6a4SAndroid Build Coastguard Worker /// event loop will invoke the mapped handler. 49*bb4ee6a4SAndroid Build Coastguard Worker pub struct EventLoop { 50*bb4ee6a4SAndroid Build Coastguard Worker fail_handle: Option<Arc<dyn FailHandle>>, 51*bb4ee6a4SAndroid Build Coastguard Worker poll_ctx: Arc<WaitContext<Descriptor>>, 52*bb4ee6a4SAndroid Build Coastguard Worker handlers: Arc<Mutex<BTreeMap<Descriptor, Weak<dyn EventHandler>>>>, 53*bb4ee6a4SAndroid Build Coastguard Worker stop_evt: Event, 54*bb4ee6a4SAndroid Build Coastguard Worker } 55*bb4ee6a4SAndroid Build Coastguard Worker 56*bb4ee6a4SAndroid Build Coastguard Worker /// Interface for event handler. 57*bb4ee6a4SAndroid Build Coastguard Worker pub trait EventHandler: Send + Sync { on_event(&self) -> anyhow::Result<()>58*bb4ee6a4SAndroid Build Coastguard Worker fn on_event(&self) -> anyhow::Result<()>; 59*bb4ee6a4SAndroid Build Coastguard Worker } 60*bb4ee6a4SAndroid Build Coastguard Worker 61*bb4ee6a4SAndroid Build Coastguard Worker impl EventLoop { 62*bb4ee6a4SAndroid Build Coastguard Worker /// Start an event loop. An optional fail handle could be passed to the event loop. start( name: String, fail_handle: Option<Arc<dyn FailHandle>>, ) -> Result<(EventLoop, thread::JoinHandle<()>)>63*bb4ee6a4SAndroid Build Coastguard Worker pub fn start( 64*bb4ee6a4SAndroid Build Coastguard Worker name: String, 65*bb4ee6a4SAndroid Build Coastguard Worker fail_handle: Option<Arc<dyn FailHandle>>, 66*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(EventLoop, thread::JoinHandle<()>)> { 67*bb4ee6a4SAndroid Build Coastguard Worker let (self_stop_evt, stop_evt) = Event::new() 68*bb4ee6a4SAndroid Build Coastguard Worker .and_then(|e| Ok((e.try_clone()?, e))) 69*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::CreateEvent)?; 70*bb4ee6a4SAndroid Build Coastguard Worker 71*bb4ee6a4SAndroid Build Coastguard Worker let fd_callbacks: Arc<Mutex<BTreeMap<Descriptor, Weak<dyn EventHandler>>>> = 72*bb4ee6a4SAndroid Build Coastguard Worker Arc::new(Mutex::new(BTreeMap::new())); 73*bb4ee6a4SAndroid Build Coastguard Worker let poll_ctx: WaitContext<Descriptor> = WaitContext::new() 74*bb4ee6a4SAndroid Build Coastguard Worker .and_then(|pc| { 75*bb4ee6a4SAndroid Build Coastguard Worker pc.add(&stop_evt, Descriptor(stop_evt.as_raw_descriptor())) 76*bb4ee6a4SAndroid Build Coastguard Worker .and(Ok(pc)) 77*bb4ee6a4SAndroid Build Coastguard Worker }) 78*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::CreateWaitContext)?; 79*bb4ee6a4SAndroid Build Coastguard Worker 80*bb4ee6a4SAndroid Build Coastguard Worker let poll_ctx = Arc::new(poll_ctx); 81*bb4ee6a4SAndroid Build Coastguard Worker let event_loop = EventLoop { 82*bb4ee6a4SAndroid Build Coastguard Worker fail_handle: fail_handle.clone(), 83*bb4ee6a4SAndroid Build Coastguard Worker poll_ctx: poll_ctx.clone(), 84*bb4ee6a4SAndroid Build Coastguard Worker handlers: fd_callbacks.clone(), 85*bb4ee6a4SAndroid Build Coastguard Worker stop_evt: self_stop_evt, 86*bb4ee6a4SAndroid Build Coastguard Worker }; 87*bb4ee6a4SAndroid Build Coastguard Worker 88*bb4ee6a4SAndroid Build Coastguard Worker let handle = thread::Builder::new() 89*bb4ee6a4SAndroid Build Coastguard Worker .name(name) 90*bb4ee6a4SAndroid Build Coastguard Worker .spawn(move || { 91*bb4ee6a4SAndroid Build Coastguard Worker loop { 92*bb4ee6a4SAndroid Build Coastguard Worker if fail_handle.failed() { 93*bb4ee6a4SAndroid Build Coastguard Worker error!("event loop already failed"); 94*bb4ee6a4SAndroid Build Coastguard Worker return; 95*bb4ee6a4SAndroid Build Coastguard Worker } 96*bb4ee6a4SAndroid Build Coastguard Worker let events = match poll_ctx.wait() { 97*bb4ee6a4SAndroid Build Coastguard Worker Ok(events) => events, 98*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 99*bb4ee6a4SAndroid Build Coastguard Worker error!("cannot wait on events {:?}", e); 100*bb4ee6a4SAndroid Build Coastguard Worker fail_handle.fail(); 101*bb4ee6a4SAndroid Build Coastguard Worker return; 102*bb4ee6a4SAndroid Build Coastguard Worker } 103*bb4ee6a4SAndroid Build Coastguard Worker }; 104*bb4ee6a4SAndroid Build Coastguard Worker for event in &events { 105*bb4ee6a4SAndroid Build Coastguard Worker let fd = event.token.as_raw_descriptor(); 106*bb4ee6a4SAndroid Build Coastguard Worker if fd == stop_evt.as_raw_descriptor() { 107*bb4ee6a4SAndroid Build Coastguard Worker return; 108*bb4ee6a4SAndroid Build Coastguard Worker } 109*bb4ee6a4SAndroid Build Coastguard Worker 110*bb4ee6a4SAndroid Build Coastguard Worker let mut locked = fd_callbacks.lock(); 111*bb4ee6a4SAndroid Build Coastguard Worker let weak_handler = match locked.get(&Descriptor(fd)) { 112*bb4ee6a4SAndroid Build Coastguard Worker Some(cb) => cb.clone(), 113*bb4ee6a4SAndroid Build Coastguard Worker None => { 114*bb4ee6a4SAndroid Build Coastguard Worker warn!("callback for fd {} already removed", fd); 115*bb4ee6a4SAndroid Build Coastguard Worker continue; 116*bb4ee6a4SAndroid Build Coastguard Worker } 117*bb4ee6a4SAndroid Build Coastguard Worker }; 118*bb4ee6a4SAndroid Build Coastguard Worker 119*bb4ee6a4SAndroid Build Coastguard Worker // If the file descriptor is hung up, remove it after calling the handler 120*bb4ee6a4SAndroid Build Coastguard Worker // one final time. 121*bb4ee6a4SAndroid Build Coastguard Worker let mut remove = event.is_hungup; 122*bb4ee6a4SAndroid Build Coastguard Worker 123*bb4ee6a4SAndroid Build Coastguard Worker if let Some(handler) = weak_handler.upgrade() { 124*bb4ee6a4SAndroid Build Coastguard Worker // Drop lock before triggering the event. 125*bb4ee6a4SAndroid Build Coastguard Worker drop(locked); 126*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = handler.on_event() { 127*bb4ee6a4SAndroid Build Coastguard Worker error!("removing event handler due to error: {:#}", e); 128*bb4ee6a4SAndroid Build Coastguard Worker remove = true; 129*bb4ee6a4SAndroid Build Coastguard Worker } 130*bb4ee6a4SAndroid Build Coastguard Worker locked = fd_callbacks.lock(); 131*bb4ee6a4SAndroid Build Coastguard Worker } else { 132*bb4ee6a4SAndroid Build Coastguard Worker // If the handler is already gone, we remove the fd. 133*bb4ee6a4SAndroid Build Coastguard Worker remove = true; 134*bb4ee6a4SAndroid Build Coastguard Worker } 135*bb4ee6a4SAndroid Build Coastguard Worker 136*bb4ee6a4SAndroid Build Coastguard Worker if remove { 137*bb4ee6a4SAndroid Build Coastguard Worker let _ = poll_ctx.delete(&event.token); 138*bb4ee6a4SAndroid Build Coastguard Worker let _ = locked.remove(&Descriptor(fd)); 139*bb4ee6a4SAndroid Build Coastguard Worker } 140*bb4ee6a4SAndroid Build Coastguard Worker } 141*bb4ee6a4SAndroid Build Coastguard Worker } 142*bb4ee6a4SAndroid Build Coastguard Worker }) 143*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::StartThread)?; 144*bb4ee6a4SAndroid Build Coastguard Worker 145*bb4ee6a4SAndroid Build Coastguard Worker Ok((event_loop, handle)) 146*bb4ee6a4SAndroid Build Coastguard Worker } 147*bb4ee6a4SAndroid Build Coastguard Worker 148*bb4ee6a4SAndroid Build Coastguard Worker /// Add a new event to event loop. The event handler will be invoked when `event` happens on 149*bb4ee6a4SAndroid Build Coastguard Worker /// `descriptor`. 150*bb4ee6a4SAndroid Build Coastguard Worker /// 151*bb4ee6a4SAndroid Build Coastguard Worker /// If the same `descriptor` is added multiple times, the old handler will be replaced. 152*bb4ee6a4SAndroid Build Coastguard Worker /// EventLoop will not keep `handler` alive, if handler is dropped when `event` is triggered, 153*bb4ee6a4SAndroid Build Coastguard Worker /// the event will be removed. add_event( &self, descriptor: &dyn AsRawDescriptor, event_type: EventType, handler: Weak<dyn EventHandler>, ) -> Result<()>154*bb4ee6a4SAndroid Build Coastguard Worker pub fn add_event( 155*bb4ee6a4SAndroid Build Coastguard Worker &self, 156*bb4ee6a4SAndroid Build Coastguard Worker descriptor: &dyn AsRawDescriptor, 157*bb4ee6a4SAndroid Build Coastguard Worker event_type: EventType, 158*bb4ee6a4SAndroid Build Coastguard Worker handler: Weak<dyn EventHandler>, 159*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> { 160*bb4ee6a4SAndroid Build Coastguard Worker if self.fail_handle.failed() { 161*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::EventLoopAlreadyFailed); 162*bb4ee6a4SAndroid Build Coastguard Worker } 163*bb4ee6a4SAndroid Build Coastguard Worker self.handlers 164*bb4ee6a4SAndroid Build Coastguard Worker .lock() 165*bb4ee6a4SAndroid Build Coastguard Worker .insert(Descriptor(descriptor.as_raw_descriptor()), handler); 166*bb4ee6a4SAndroid Build Coastguard Worker self.poll_ctx 167*bb4ee6a4SAndroid Build Coastguard Worker .add_for_event( 168*bb4ee6a4SAndroid Build Coastguard Worker descriptor, 169*bb4ee6a4SAndroid Build Coastguard Worker event_type, 170*bb4ee6a4SAndroid Build Coastguard Worker Descriptor(descriptor.as_raw_descriptor()), 171*bb4ee6a4SAndroid Build Coastguard Worker ) 172*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::WaitContextAddDescriptor) 173*bb4ee6a4SAndroid Build Coastguard Worker } 174*bb4ee6a4SAndroid Build Coastguard Worker 175*bb4ee6a4SAndroid Build Coastguard Worker /// Removes event for this `descriptor`. This function is safe to call even when the 176*bb4ee6a4SAndroid Build Coastguard Worker /// `descriptor` is not actively being polled because it's been paused. 177*bb4ee6a4SAndroid Build Coastguard Worker /// 178*bb4ee6a4SAndroid Build Coastguard Worker /// EventLoop does not guarantee all events for `descriptor` is handled. remove_event_for_descriptor(&self, descriptor: &dyn AsRawDescriptor) -> Result<()>179*bb4ee6a4SAndroid Build Coastguard Worker pub fn remove_event_for_descriptor(&self, descriptor: &dyn AsRawDescriptor) -> Result<()> { 180*bb4ee6a4SAndroid Build Coastguard Worker if self.fail_handle.failed() { 181*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::EventLoopAlreadyFailed); 182*bb4ee6a4SAndroid Build Coastguard Worker } 183*bb4ee6a4SAndroid Build Coastguard Worker self.poll_ctx 184*bb4ee6a4SAndroid Build Coastguard Worker .delete(descriptor) 185*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::WaitContextDeleteDescriptor)?; 186*bb4ee6a4SAndroid Build Coastguard Worker self.handlers 187*bb4ee6a4SAndroid Build Coastguard Worker .lock() 188*bb4ee6a4SAndroid Build Coastguard Worker .remove(&Descriptor(descriptor.as_raw_descriptor())); 189*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 190*bb4ee6a4SAndroid Build Coastguard Worker } 191*bb4ee6a4SAndroid Build Coastguard Worker 192*bb4ee6a4SAndroid Build Coastguard Worker /// Pauses polling on the given `descriptor`. It keeps a reference to the `descriptor` and its 193*bb4ee6a4SAndroid Build Coastguard Worker /// handler so it can be resumed by calling `resume_event_for_descriptor()`. pause_event_for_descriptor(&self, descriptor: &dyn AsRawDescriptor) -> Result<()>194*bb4ee6a4SAndroid Build Coastguard Worker pub fn pause_event_for_descriptor(&self, descriptor: &dyn AsRawDescriptor) -> Result<()> { 195*bb4ee6a4SAndroid Build Coastguard Worker if self.fail_handle.failed() { 196*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::EventLoopAlreadyFailed); 197*bb4ee6a4SAndroid Build Coastguard Worker } 198*bb4ee6a4SAndroid Build Coastguard Worker self.poll_ctx 199*bb4ee6a4SAndroid Build Coastguard Worker .delete(descriptor) 200*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::WaitContextDeleteDescriptor)?; 201*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 202*bb4ee6a4SAndroid Build Coastguard Worker } 203*bb4ee6a4SAndroid Build Coastguard Worker 204*bb4ee6a4SAndroid Build Coastguard Worker /// Resumes polling on the given `descriptor` with the previously-provided handler. If 205*bb4ee6a4SAndroid Build Coastguard Worker /// `descriptor` was not paused beforehand, this function does nothing. If `descriptor` does 206*bb4ee6a4SAndroid Build Coastguard Worker /// not exist in the event loop, it returns an error. 207*bb4ee6a4SAndroid Build Coastguard Worker /// `event_type` does not need to match the previously registered event type. resume_event_for_descriptor( &self, descriptor: &dyn AsRawDescriptor, event_type: EventType, ) -> Result<()>208*bb4ee6a4SAndroid Build Coastguard Worker pub fn resume_event_for_descriptor( 209*bb4ee6a4SAndroid Build Coastguard Worker &self, 210*bb4ee6a4SAndroid Build Coastguard Worker descriptor: &dyn AsRawDescriptor, 211*bb4ee6a4SAndroid Build Coastguard Worker event_type: EventType, 212*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> { 213*bb4ee6a4SAndroid Build Coastguard Worker let handler = self 214*bb4ee6a4SAndroid Build Coastguard Worker .handlers 215*bb4ee6a4SAndroid Build Coastguard Worker .lock() 216*bb4ee6a4SAndroid Build Coastguard Worker .get(&Descriptor(descriptor.as_raw_descriptor())) 217*bb4ee6a4SAndroid Build Coastguard Worker .ok_or(Error::EventLoopMissingHandler)? 218*bb4ee6a4SAndroid Build Coastguard Worker .clone(); 219*bb4ee6a4SAndroid Build Coastguard Worker self.add_event(descriptor, event_type, handler) 220*bb4ee6a4SAndroid Build Coastguard Worker } 221*bb4ee6a4SAndroid Build Coastguard Worker 222*bb4ee6a4SAndroid Build Coastguard Worker /// Stops this event loop asynchronously. Previous events might not be handled. stop(&self)223*bb4ee6a4SAndroid Build Coastguard Worker pub fn stop(&self) { 224*bb4ee6a4SAndroid Build Coastguard Worker match self.stop_evt.signal() { 225*bb4ee6a4SAndroid Build Coastguard Worker Ok(_) => {} 226*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => { 227*bb4ee6a4SAndroid Build Coastguard Worker error!("fail to send event loop stop event, it might already stopped"); 228*bb4ee6a4SAndroid Build Coastguard Worker } 229*bb4ee6a4SAndroid Build Coastguard Worker } 230*bb4ee6a4SAndroid Build Coastguard Worker } 231*bb4ee6a4SAndroid Build Coastguard Worker } 232*bb4ee6a4SAndroid Build Coastguard Worker 233*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)] 234*bb4ee6a4SAndroid Build Coastguard Worker mod tests { 235*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc; 236*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Condvar; 237*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Mutex; 238*bb4ee6a4SAndroid Build Coastguard Worker 239*bb4ee6a4SAndroid Build Coastguard Worker use base::Event; 240*bb4ee6a4SAndroid Build Coastguard Worker 241*bb4ee6a4SAndroid Build Coastguard Worker use super::*; 242*bb4ee6a4SAndroid Build Coastguard Worker 243*bb4ee6a4SAndroid Build Coastguard Worker struct EventLoopTestHandler { 244*bb4ee6a4SAndroid Build Coastguard Worker val: Mutex<u8>, 245*bb4ee6a4SAndroid Build Coastguard Worker cvar: Condvar, 246*bb4ee6a4SAndroid Build Coastguard Worker evt: Event, 247*bb4ee6a4SAndroid Build Coastguard Worker } 248*bb4ee6a4SAndroid Build Coastguard Worker 249*bb4ee6a4SAndroid Build Coastguard Worker impl EventHandler for EventLoopTestHandler { on_event(&self) -> anyhow::Result<()>250*bb4ee6a4SAndroid Build Coastguard Worker fn on_event(&self) -> anyhow::Result<()> { 251*bb4ee6a4SAndroid Build Coastguard Worker self.evt.wait().unwrap(); 252*bb4ee6a4SAndroid Build Coastguard Worker *self.val.lock().unwrap() += 1; 253*bb4ee6a4SAndroid Build Coastguard Worker self.cvar.notify_one(); 254*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 255*bb4ee6a4SAndroid Build Coastguard Worker } 256*bb4ee6a4SAndroid Build Coastguard Worker } 257*bb4ee6a4SAndroid Build Coastguard Worker 258*bb4ee6a4SAndroid Build Coastguard Worker #[test] event_loop_test()259*bb4ee6a4SAndroid Build Coastguard Worker fn event_loop_test() { 260*bb4ee6a4SAndroid Build Coastguard Worker let (l, j) = EventLoop::start("test".to_string(), None).unwrap(); 261*bb4ee6a4SAndroid Build Coastguard Worker let (self_evt, evt) = match Event::new().and_then(|e| Ok((e.try_clone()?, e))) { 262*bb4ee6a4SAndroid Build Coastguard Worker Ok(v) => v, 263*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 264*bb4ee6a4SAndroid Build Coastguard Worker error!("failed creating Event pair: {:?}", e); 265*bb4ee6a4SAndroid Build Coastguard Worker return; 266*bb4ee6a4SAndroid Build Coastguard Worker } 267*bb4ee6a4SAndroid Build Coastguard Worker }; 268*bb4ee6a4SAndroid Build Coastguard Worker let h = Arc::new(EventLoopTestHandler { 269*bb4ee6a4SAndroid Build Coastguard Worker val: Mutex::new(0), 270*bb4ee6a4SAndroid Build Coastguard Worker cvar: Condvar::new(), 271*bb4ee6a4SAndroid Build Coastguard Worker evt, 272*bb4ee6a4SAndroid Build Coastguard Worker }); 273*bb4ee6a4SAndroid Build Coastguard Worker let t: Arc<dyn EventHandler> = h.clone(); 274*bb4ee6a4SAndroid Build Coastguard Worker l.add_event(&h.evt, EventType::Read, Arc::downgrade(&t)) 275*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 276*bb4ee6a4SAndroid Build Coastguard Worker self_evt.signal().unwrap(); 277*bb4ee6a4SAndroid Build Coastguard Worker { 278*bb4ee6a4SAndroid Build Coastguard Worker let mut val = h.val.lock().unwrap(); 279*bb4ee6a4SAndroid Build Coastguard Worker while *val < 1 { 280*bb4ee6a4SAndroid Build Coastguard Worker val = h.cvar.wait(val).unwrap(); 281*bb4ee6a4SAndroid Build Coastguard Worker } 282*bb4ee6a4SAndroid Build Coastguard Worker } 283*bb4ee6a4SAndroid Build Coastguard Worker l.stop(); 284*bb4ee6a4SAndroid Build Coastguard Worker j.join().unwrap(); 285*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(*(h.val.lock().unwrap()), 1); 286*bb4ee6a4SAndroid Build Coastguard Worker } 287*bb4ee6a4SAndroid Build Coastguard Worker } 288