Introduce AsyncAppContext and simplify spawning

Now when you call spawn in various context, you pass an FnOnce that is called with an AsyncAppContext and returns a static future. This allows you to write async code similar to how our tests work, borrowing the guts of the AsyncAppContext when needed to interact, but using normal async await semantics instead of callbacks.

Co-Authored-By: Max Brunsfeld <maxbrunsfeld@gmail.com>
This commit is contained in:
Nathan Sobo
2021-05-12 15:16:49 -06:00
co-authored by Max Brunsfeld
parent d0f69c76e1
commit fa6bd1f926
6 changed files with 388 additions and 525 deletions
+15 -15
View File
@@ -4,11 +4,9 @@ mod selection;
mod text;
pub use anchor::*;
use futures_core::future::LocalBoxFuture;
pub use point::*;
use seahash::SeaHasher;
pub use selection::*;
use smol::future::FutureExt;
pub use text::*;
use crate::{
@@ -19,7 +17,7 @@ use crate::{
worktree::FileHandle,
};
use anyhow::{anyhow, Result};
use gpui::{Entity, ModelContext};
use gpui::{Entity, ModelContext, Task};
use lazy_static::lazy_static;
use rand::prelude::*;
use std::{
@@ -475,21 +473,23 @@ impl Buffer {
&mut self,
new_file: Option<FileHandle>,
ctx: &mut ModelContext<Self>,
) -> LocalBoxFuture<'static, Result<()>> {
) -> Task<Result<()>> {
let snapshot = self.snapshot();
let version = self.version.clone();
if let Some(file) = new_file.as_ref().or(self.file.as_ref()) {
let save_task = file.save(snapshot, ctx.as_ref());
ctx.spawn(save_task, |me, save_result, ctx| {
if save_result.is_ok() {
me.did_save(version, new_file, ctx);
let file = self.file.clone();
let handle = ctx.handle();
ctx.spawn(|mut ctx| async move {
if let Some(file) = new_file.as_ref().or(file.as_ref()) {
let result = ctx.read(|ctx| file.save(snapshot, ctx.as_ref())).await;
if result.is_ok() {
handle.update(&mut ctx, |me, ctx| me.did_save(version, new_file, ctx));
}
save_result
})
.boxed_local()
} else {
async { Ok(()) }.boxed_local()
}
result
} else {
Ok(())
}
})
}
fn did_save(
+14 -17
View File
@@ -4,11 +4,10 @@ use super::{
};
use crate::{settings::Settings, util::post_inc, workspace, worktree::FileHandle};
use anyhow::Result;
use futures_core::future::LocalBoxFuture;
use gpui::{
fonts::Properties as FontProperties, geometry::vector::Vector2F, keymap::Binding, text_layout,
AppContext, ClipboardItem, Element, ElementBox, Entity, FontCache, ModelHandle,
MutableAppContext, TextLayoutCache, View, ViewContext, WeakViewHandle,
MutableAppContext, Task, TextLayoutCache, View, ViewContext, WeakViewHandle,
};
use parking_lot::Mutex;
use postage::watch;
@@ -2348,13 +2347,13 @@ impl BufferView {
ctx.notify();
let epoch = self.next_blink_epoch();
ctx.spawn(
async move {
Timer::after(CURSOR_BLINK_INTERVAL).await;
epoch
},
Self::resume_cursor_blinking,
)
let handle = ctx.handle();
ctx.spawn(|mut ctx| async move {
Timer::after(CURSOR_BLINK_INTERVAL).await;
handle.update(&mut ctx, |this, ctx| {
this.resume_cursor_blinking(epoch, ctx);
})
})
.detach();
}
@@ -2371,13 +2370,11 @@ impl BufferView {
ctx.notify();
let epoch = self.next_blink_epoch();
ctx.spawn(
async move {
Timer::after(CURSOR_BLINK_INTERVAL).await;
epoch
},
Self::blink_cursors,
)
let handle = ctx.handle();
ctx.spawn(|mut ctx| async move {
Timer::after(CURSOR_BLINK_INTERVAL).await;
handle.update(&mut ctx, |this, ctx| this.blink_cursors(epoch, ctx));
})
.detach();
}
}
@@ -2498,7 +2495,7 @@ impl workspace::ItemView for BufferView {
&mut self,
new_file: Option<FileHandle>,
ctx: &mut ViewContext<Self>,
) -> LocalBoxFuture<'static, Result<()>> {
) -> Task<Result<()>> {
self.buffer.update(ctx, |b, ctx| b.save(new_file, ctx))
}