xref: /aosp_15_r20/external/crosvm/devices/src/utils/event_loop.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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