1 // Copyright 2018 The Chromium OS Authors. All rights reserved. 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 super::{Error, Result}; 6 use super::{EventHandler, EventLoop}; 7 8 use anyhow::Context; 9 use base::{Event, WatchingEvents}; 10 use std::mem; 11 use std::sync::Arc; 12 use sync::Mutex; 13 14 /// Async Job Queue can schedule async jobs. 15 pub struct AsyncJobQueue { 16 jobs: Mutex<Vec<Box<dyn FnMut() + Send>>>, 17 evt: Event, 18 } 19 20 impl AsyncJobQueue { 21 /// Init job queue on event loop. init(event_loop: &EventLoop) -> Result<Arc<AsyncJobQueue>>22 pub fn init(event_loop: &EventLoop) -> Result<Arc<AsyncJobQueue>> { 23 let evt = Event::new().map_err(Error::CreateEvent)?; 24 let queue = Arc::new(AsyncJobQueue { 25 jobs: Mutex::new(Vec::new()), 26 evt, 27 }); 28 let handler: Arc<dyn EventHandler> = queue.clone(); 29 event_loop.add_event( 30 &queue.evt, 31 WatchingEvents::empty().set_read(), 32 Arc::downgrade(&handler), 33 )?; 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.write(1).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, but the value is not important. 47 let _ = self.evt.read().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