// 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>>, evt: EventFd, } impl AsyncJobQueue { /// Init job queue on event loop. pub fn init(event_loop: &EventLoop) -> Result> { let evt = EventFd::new().map_err(Error::CreateEventFd)?; let queue = Arc::new(AsyncJobQueue { jobs: Mutex::new(Vec::new()), evt, }); let handler: Arc = 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(&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(()) } }