helix-mirror/helix-term/src/job.rs

101 lines
2.6 KiB
Rust
Raw Normal View History

2021-06-28 16:48:38 +04:00
use helix_view::Editor;
use crate::compositor::Compositor;
use futures_util::future::{self, BoxFuture, Future, FutureExt};
use futures_util::stream::{FuturesUnordered, StreamExt};
2021-06-28 16:48:38 +04:00
pub type Callback = Box<dyn FnOnce(&mut Editor, &mut Compositor) + Send>;
pub type JobFuture = BoxFuture<'static, anyhow::Result<Option<Callback>>>;
pub struct Job {
pub future: BoxFuture<'static, anyhow::Result<Option<Callback>>>,
/// Do we need to wait for this job to finish before exiting?
pub wait: bool,
}
#[derive(Default)]
pub struct Jobs {
2021-07-03 07:30:13 +04:00
pub futures: FuturesUnordered<JobFuture>,
2021-06-28 16:48:38 +04:00
/// These are the ones that need to complete before we exit.
2021-07-03 07:30:13 +04:00
pub wait_futures: FuturesUnordered<JobFuture>,
2021-06-28 16:48:38 +04:00
}
impl Job {
pub fn new<F: Future<Output = anyhow::Result<()>> + Send + 'static>(f: F) -> Self {
Self {
2021-06-28 16:48:38 +04:00
future: f.map(|r| r.map(|()| None)).boxed(),
wait: false,
}
}
pub fn with_callback<F: Future<Output = anyhow::Result<Callback>> + Send + 'static>(
f: F,
) -> Self {
Self {
2021-06-28 17:00:44 +04:00
future: f.map(|r| r.map(Some)).boxed(),
2021-06-28 16:48:38 +04:00
wait: false,
}
}
pub fn wait_before_exiting(mut self) -> Self {
2021-06-28 16:48:38 +04:00
self.wait = true;
self
}
}
impl Jobs {
pub fn new() -> Self {
Self::default()
2021-06-28 16:48:38 +04:00
}
pub fn spawn<F: Future<Output = anyhow::Result<()>> + Send + 'static>(&mut self, f: F) {
self.add(Job::new(f));
}
pub fn callback<F: Future<Output = anyhow::Result<Callback>> + Send + 'static>(
&mut self,
f: F,
) {
self.add(Job::with_callback(f));
}
pub fn handle_callback(
&self,
2021-06-28 16:48:38 +04:00
editor: &mut Editor,
compositor: &mut Compositor,
call: anyhow::Result<Option<Callback>>,
) {
match call {
Ok(None) => {}
Ok(Some(call)) => {
call(editor, compositor);
}
Err(e) => {
editor.set_error(format!("Async job failed: {}", e));
}
}
}
2021-07-03 07:30:13 +04:00
pub async fn next_job(&mut self) -> Option<anyhow::Result<Option<Callback>>> {
tokio::select! {
event = self.futures.next() => { event }
event = self.wait_futures.next() => { event }
}
2021-06-28 16:48:38 +04:00
}
pub fn add(&self, j: Job) {
2021-06-28 16:48:38 +04:00
if j.wait {
self.wait_futures.push(j.future);
} else {
self.futures.push(j.future);
}
}
/// Blocks until all the jobs that need to be waited on are done.
pub fn finish(&mut self) {
let wait_futures = std::mem::take(&mut self.wait_futures);
helix_lsp::block_on(wait_futures.for_each(|_| future::ready(())));
}
}