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 use base::{error, Event, WatchingEvents}; 8 use std::mem; 9 use std::sync::Arc; 10 use sync::Mutex; 11 12 /// Async Job Queue can schedule async jobs. 13 pub struct AsyncJobQueue { 14 jobs: Mutex<Vec<Box<dyn FnMut() + Send>>>, 15 evt: Event, 16 } 17 18 impl AsyncJobQueue { 19 /// Init job queue on event loop. init(event_loop: &EventLoop) -> Result<Arc<AsyncJobQueue>>20 pub fn init(event_loop: &EventLoop) -> Result<Arc<AsyncJobQueue>> { 21 let evt = Event::new().map_err(Error::CreateEvent)?; 22 let queue = Arc::new(AsyncJobQueue { 23 jobs: Mutex::new(Vec::new()), 24 evt, 25 }); 26 let handler: Arc<dyn EventHandler> = queue.clone(); 27 event_loop.add_event( 28 &queue.evt, 29 WatchingEvents::empty().set_read(), 30 Arc::downgrade(&handler), 31 )?; 32 Ok(queue) 33 } 34 35 /// Queue a new job. It will be invoked on event loop. queue_job<T: Fn() + 'static + Send>(&self, cb: T) -> Result<()>36 pub fn queue_job<T: Fn() + 'static + Send>(&self, cb: T) -> Result<()> { 37 self.jobs.lock().push(Box::new(cb)); 38 self.evt.write(1).map_err(Error::WriteEvent) 39 } 40 } 41 42 impl EventHandler for AsyncJobQueue { on_event(&self) -> std::result::Result<(), ()>43 fn on_event(&self) -> std::result::Result<(), ()> { 44 // We want to read out the event, but the value is not important. 45 match self.evt.read() { 46 Ok(_) => {} 47 Err(e) => { 48 error!("read event failed {}", e); 49 return Err(()); 50 } 51 } 52 53 let jobs = mem::replace(&mut *self.jobs.lock(), Vec::new()); 54 for mut cb in jobs { 55 cb(); 56 } 57 Ok(()) 58 } 59 } 60