diff options
author | Jingkui Wang <jkwang@google.com> | 2019-03-07 13:43:33 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-03-13 21:04:57 -0700 |
commit | 415ee63e043119aecdc2907d83f18a538698ad2d (patch) | |
tree | 22dc366816cac02349908e038d1e5a7c4ce4487e /devices/src/utils/async_job_queue.rs | |
parent | ea75bd164aedca9c429f1a9421ba944d8c786a50 (diff) | |
download | crosvm-415ee63e043119aecdc2907d83f18a538698ad2d.tar crosvm-415ee63e043119aecdc2907d83f18a538698ad2d.tar.gz crosvm-415ee63e043119aecdc2907d83f18a538698ad2d.tar.bz2 crosvm-415ee63e043119aecdc2907d83f18a538698ad2d.tar.lz crosvm-415ee63e043119aecdc2907d83f18a538698ad2d.tar.xz crosvm-415ee63e043119aecdc2907d83f18a538698ad2d.tar.zst crosvm-415ee63e043119aecdc2907d83f18a538698ad2d.zip |
add utils for device implementations
event_loop: event loop based on poll context. async_job_queue: queue a job, it will be invoked on event loop. This could be used to invoke a function without holding any locks. BUG=chromium:831850 TEST=local build Change-Id: Iab61ac43221bf5d635a0138073d7f88401e5ab07 Reviewed-on: https://chromium-review.googlesource.com/1509852 Commit-Ready: Jingkui Wang <jkwang@google.com> Tested-by: Jingkui Wang <jkwang@google.com> Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Zach Reizner <zachr@chromium.org>
Diffstat (limited to 'devices/src/utils/async_job_queue.rs')
-rw-r--r-- | devices/src/utils/async_job_queue.rs | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/devices/src/utils/async_job_queue.rs b/devices/src/utils/async_job_queue.rs new file mode 100644 index 0000000..bc99c05 --- /dev/null +++ b/devices/src/utils/async_job_queue.rs @@ -0,0 +1,60 @@ +// Copyright 2018 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +use super::{Error, Result}; +use super::{EventHandler, EventLoop}; +use std::mem; +use std::os::unix::io::RawFd; +use std::sync::Arc; +use sync::Mutex; +use sys_util::{EventFd, WatchingEvents}; + +/// Async Job Queue can schedule async jobs. +pub struct AsyncJobQueue { + jobs: Mutex<Vec<Box<FnMut() + 'static + Send>>>, + evt: EventFd, +} + +impl AsyncJobQueue { + /// Init job queue on event loop. + pub fn init(event_loop: &EventLoop) -> Result<Arc<AsyncJobQueue>> { + let evt = EventFd::new().map_err(Error::CreateEventFd)?; + let queue = Arc::new(AsyncJobQueue { + jobs: Mutex::new(Vec::new()), + evt, + }); + let handler: Arc<EventHandler> = queue.clone(); + event_loop.add_event( + &queue.evt, + WatchingEvents::empty().set_read(), + Arc::downgrade(&handler), + ); + Ok(queue) + } + + /// Queue a new job. It will be invoked on event loop. + pub fn queue_job<T: Fn() + 'static + Send>(&self, cb: T) -> Result<()> { + self.jobs.lock().push(Box::new(cb)); + self.evt.write(1).map_err(Error::WriteEventFd) + } +} + +impl EventHandler for AsyncJobQueue { + fn on_event(&self, _fd: RawFd) -> std::result::Result<(), ()> { + // We want to read out the event, but the value is not important. + match self.evt.read() { + Ok(_) => {} + Err(e) => { + error!("read event fd failed {}", e); + return Err(()); + } + } + + let jobs = mem::replace(&mut *self.jobs.lock(), Vec::new()); + for mut cb in jobs { + cb(); + } + Ok(()) + } +} |