xref: /aosp_15_r20/external/crosvm/devices/src/utils/async_job_queue.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2018 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::mem;
6 use std::sync::Arc;
7 
8 use anyhow::Context;
9 use base::Event;
10 use base::EventType;
11 use sync::Mutex;
12 
13 use super::Error;
14 use super::EventHandler;
15 use super::EventLoop;
16 use super::Result;
17 
18 /// Async Job Queue can schedule async jobs.
19 pub struct AsyncJobQueue {
20     jobs: Mutex<Vec<Box<dyn FnMut() + Send>>>,
21     evt: Event,
22 }
23 
24 impl AsyncJobQueue {
25     /// Init job queue on event loop.
init(event_loop: &EventLoop) -> Result<Arc<AsyncJobQueue>>26     pub fn init(event_loop: &EventLoop) -> Result<Arc<AsyncJobQueue>> {
27         let evt = Event::new().map_err(Error::CreateEvent)?;
28         let queue = Arc::new(AsyncJobQueue {
29             jobs: Mutex::new(Vec::new()),
30             evt,
31         });
32         let handler: Arc<dyn EventHandler> = queue.clone();
33         event_loop.add_event(&queue.evt, EventType::Read, Arc::downgrade(&handler))?;
34         Ok(queue)
35     }
36 
37     /// Queue a new job. It will be invoked on event loop.
queue_job<T: Fn() + 'static + Send>(&self, cb: T) -> Result<()>38     pub fn queue_job<T: Fn() + 'static + Send>(&self, cb: T) -> Result<()> {
39         self.jobs.lock().push(Box::new(cb));
40         self.evt.signal().map_err(Error::WriteEvent)
41     }
42 }
43 
44 impl EventHandler for AsyncJobQueue {
on_event(&self) -> anyhow::Result<()>45     fn on_event(&self) -> anyhow::Result<()> {
46         // We want to read out the event.
47         self.evt.wait().context("read event failed")?;
48 
49         let jobs = mem::take(&mut *self.jobs.lock());
50         for mut cb in jobs {
51             cb();
52         }
53         Ok(())
54     }
55 }
56