Make the gpui_tokio crate generic over the context it spawns (#23995)
Part of #21092 Makes `Tokio::spawn` generic over any `AppContext`. Also removes a stray `model_context` I missed Release Notes: - N/A
This commit is contained in:
parent
ff43b6875b
commit
517e519bdc
7 changed files with 133 additions and 18 deletions
|
@ -22,9 +22,9 @@ use slotmap::SlotMap;
|
|||
|
||||
pub use async_context::*;
|
||||
use collections::{FxHashMap, FxHashSet, HashMap, VecDeque};
|
||||
pub use context::*;
|
||||
pub use entity_map::*;
|
||||
use http_client::HttpClient;
|
||||
pub use model_context::*;
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub use test_context::*;
|
||||
use util::ResultExt;
|
||||
|
@ -41,8 +41,8 @@ use crate::{
|
|||
};
|
||||
|
||||
mod async_context;
|
||||
mod context;
|
||||
mod entity_map;
|
||||
mod model_context;
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
mod test_context;
|
||||
|
||||
|
@ -1667,6 +1667,21 @@ impl AppContext for App {
|
|||
|
||||
Ok(read(view, self))
|
||||
}
|
||||
|
||||
fn background_spawn<R>(&self, future: impl Future<Output = R> + Send + 'static) -> Task<R>
|
||||
where
|
||||
R: Send + 'static,
|
||||
{
|
||||
self.background_executor.spawn(future)
|
||||
}
|
||||
|
||||
fn read_global<G, R>(&self, callback: impl FnOnce(&G, &App) -> R) -> Self::Result<R>
|
||||
where
|
||||
G: Global,
|
||||
{
|
||||
let mut g = self.global::<G>();
|
||||
callback(&g, self)
|
||||
}
|
||||
}
|
||||
|
||||
/// These effects are processed at the end of each application update cycle.
|
||||
|
|
|
@ -104,6 +104,22 @@ impl AppContext for AsyncApp {
|
|||
let lock = app.borrow();
|
||||
lock.read_window(window, read)
|
||||
}
|
||||
|
||||
fn background_spawn<R>(&self, future: impl Future<Output = R> + Send + 'static) -> Task<R>
|
||||
where
|
||||
R: Send + 'static,
|
||||
{
|
||||
self.background_executor.spawn(future)
|
||||
}
|
||||
|
||||
fn read_global<G, R>(&self, callback: impl FnOnce(&G, &App) -> R) -> Self::Result<R>
|
||||
where
|
||||
G: Global,
|
||||
{
|
||||
let app = self.app.upgrade().context("app was released")?;
|
||||
let mut lock = app.borrow_mut();
|
||||
Ok(lock.update(|this| this.read_global(callback)))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncApp {
|
||||
|
@ -367,6 +383,20 @@ impl AppContext for AsyncWindowContext {
|
|||
{
|
||||
self.app.read_window(window, read)
|
||||
}
|
||||
|
||||
fn background_spawn<R>(&self, future: impl Future<Output = R> + Send + 'static) -> Task<R>
|
||||
where
|
||||
R: Send + 'static,
|
||||
{
|
||||
self.app.background_executor.spawn(future)
|
||||
}
|
||||
|
||||
fn read_global<G, R>(&self, callback: impl FnOnce(&G, &App) -> R) -> Result<R>
|
||||
where
|
||||
G: Global,
|
||||
{
|
||||
self.app.read_global(callback)
|
||||
}
|
||||
}
|
||||
|
||||
impl VisualContext for AsyncWindowContext {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
AnyView, AnyWindowHandle, App, AppContext, AsyncApp, DispatchPhase, Effect, EntityId,
|
||||
EventEmitter, FocusHandle, FocusOutEvent, Focusable, Global, KeystrokeObserver, Reservation,
|
||||
SubscriberSet, Subscription, Task, WeakEntity, WeakFocusHandle, Window, WindowHandle,
|
||||
AnyView, AnyWindowHandle, AppContext, AsyncApp, DispatchPhase, Effect, EntityId, EventEmitter,
|
||||
FocusHandle, FocusOutEvent, Focusable, Global, KeystrokeObserver, Reservation, SubscriberSet,
|
||||
Subscription, Task, WeakEntity, WeakFocusHandle, Window, WindowHandle,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use derive_more::{Deref, DerefMut};
|
||||
|
@ -13,7 +13,7 @@ use std::{
|
|||
sync::Arc,
|
||||
};
|
||||
|
||||
use super::{AsyncWindowContext, Entity, KeystrokeEvent};
|
||||
use super::{App, AsyncWindowContext, Entity, KeystrokeEvent};
|
||||
|
||||
/// The app context, with specialized behavior for the given model.
|
||||
#[derive(Deref, DerefMut)]
|
||||
|
@ -717,6 +717,20 @@ impl<'a, T> AppContext for Context<'a, T> {
|
|||
{
|
||||
self.app.read_window(window, read)
|
||||
}
|
||||
|
||||
fn background_spawn<R>(&self, future: impl Future<Output = R> + Send + 'static) -> Task<R>
|
||||
where
|
||||
R: Send + 'static,
|
||||
{
|
||||
self.app.background_executor.spawn(future)
|
||||
}
|
||||
|
||||
fn read_global<G, R>(&self, callback: impl FnOnce(&G, &App) -> R) -> Self::Result<R>
|
||||
where
|
||||
G: Global,
|
||||
{
|
||||
self.app.read_global(callback)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Borrow<App> for Context<'_, T> {
|
|
@ -94,6 +94,21 @@ impl AppContext for TestAppContext {
|
|||
let app = self.app.borrow();
|
||||
app.read_window(window, read)
|
||||
}
|
||||
|
||||
fn background_spawn<R>(&self, future: impl Future<Output = R> + Send + 'static) -> Task<R>
|
||||
where
|
||||
R: Send + 'static,
|
||||
{
|
||||
self.background_executor.spawn(future)
|
||||
}
|
||||
|
||||
fn read_global<G, R>(&self, callback: impl FnOnce(&G, &App) -> R) -> Self::Result<R>
|
||||
where
|
||||
G: Global,
|
||||
{
|
||||
let app = self.app.borrow();
|
||||
app.read_global(callback)
|
||||
}
|
||||
}
|
||||
|
||||
impl TestAppContext {
|
||||
|
@ -906,6 +921,20 @@ impl AppContext for VisualTestContext {
|
|||
{
|
||||
self.cx.read_window(window, read)
|
||||
}
|
||||
|
||||
fn background_spawn<R>(&self, future: impl Future<Output = R> + Send + 'static) -> Task<R>
|
||||
where
|
||||
R: Send + 'static,
|
||||
{
|
||||
self.cx.background_spawn(future)
|
||||
}
|
||||
|
||||
fn read_global<G, R>(&self, callback: impl FnOnce(&G, &App) -> R) -> Self::Result<R>
|
||||
where
|
||||
G: Global,
|
||||
{
|
||||
self.cx.read_global(callback)
|
||||
}
|
||||
}
|
||||
|
||||
impl VisualContext for VisualTestContext {
|
||||
|
|
|
@ -155,7 +155,7 @@ pub use util::arc_cow::ArcCow;
|
|||
pub use view::*;
|
||||
pub use window::*;
|
||||
|
||||
use std::{any::Any, borrow::BorrowMut};
|
||||
use std::{any::Any, borrow::BorrowMut, future::Future};
|
||||
use taffy::TaffyLayoutEngine;
|
||||
|
||||
/// The context trait, allows the different contexts in GPUI to be used
|
||||
|
@ -215,6 +215,16 @@ pub trait AppContext {
|
|||
) -> Result<R>
|
||||
where
|
||||
T: 'static;
|
||||
|
||||
/// Spawn a future on a background thread
|
||||
fn background_spawn<R>(&self, future: impl Future<Output = R> + Send + 'static) -> Task<R>
|
||||
where
|
||||
R: Send + 'static;
|
||||
|
||||
/// Read a global from this app context
|
||||
fn read_global<G, R>(&self, callback: impl FnOnce(&G, &App) -> R) -> Self::Result<R>
|
||||
where
|
||||
G: Global;
|
||||
}
|
||||
|
||||
/// Returned by [Context::reserve_entity] to later be passed to [Context::insert_model].
|
||||
|
|
|
@ -81,6 +81,20 @@ pub fn derive_app_context(input: TokenStream) -> TokenStream {
|
|||
{
|
||||
self.#app_variable.read_window(window, read)
|
||||
}
|
||||
|
||||
fn background_spawn<R>(&self, future: impl std::future::Future<Output = R> + Send + 'static) -> gpui::Task<R>
|
||||
where
|
||||
R: Send + 'static,
|
||||
{
|
||||
self.#app_variable.background_spawn(future)
|
||||
}
|
||||
|
||||
fn read_global<G, R>(&self, callback: impl FnOnce(&G, &gpui::App) -> R) -> Self::Result<R>
|
||||
where
|
||||
G: gpui::Global,
|
||||
{
|
||||
self.#app_variable.read_global(callback)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::future::Future;
|
||||
|
||||
use gpui::{App, Global, ReadGlobal, Task};
|
||||
use gpui::{App, AppContext, Global, ReadGlobal, Task};
|
||||
use tokio::task::JoinError;
|
||||
use util::defer;
|
||||
|
||||
|
@ -32,20 +32,23 @@ pub struct Tokio {}
|
|||
impl Tokio {
|
||||
/// Spawns the given future on Tokio's thread pool, and returns it via a GPUI task
|
||||
/// Note that the Tokio task will be cancelled if the GPUI task is dropped
|
||||
pub fn spawn<Fut, R>(cx: &mut App, f: Fut) -> Task<Result<R, JoinError>>
|
||||
pub fn spawn<C, Fut, R>(cx: &mut C, f: Fut) -> C::Result<Task<Result<R, JoinError>>>
|
||||
where
|
||||
C: AppContext,
|
||||
Fut: Future<Output = R> + Send + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
let join_handle = GlobalTokio::global(cx).runtime.spawn(f);
|
||||
let abort_handle = join_handle.abort_handle();
|
||||
let cancel = defer(move || {
|
||||
abort_handle.abort();
|
||||
});
|
||||
cx.background_executor().spawn(async move {
|
||||
let result = join_handle.await;
|
||||
drop(cancel);
|
||||
result
|
||||
cx.read_global(|tokio: &GlobalTokio, cx| {
|
||||
let join_handle = tokio.runtime.spawn(f);
|
||||
let abort_handle = join_handle.abort_handle();
|
||||
let cancel = defer(move || {
|
||||
abort_handle.abort();
|
||||
});
|
||||
cx.background_spawn(async move {
|
||||
let result = join_handle.await;
|
||||
drop(cancel);
|
||||
result
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue