blob: 76ae8c77c45a93020773e6edd2d242f526608258 [file] [log] [blame]
// 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::sync::Arc;
use sync::Mutex;
use sys_util::{error, EventFd, WatchingEvents};
/// Async Job Queue can schedule async jobs.
pub struct AsyncJobQueue {
jobs: Mutex<Vec<Box<dyn FnMut() + 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<dyn 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) -> 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(())
}
}