From 11b6d9e33ac5b3c4bbaff7f8b21ce7d782378d40 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 1 Nov 2023 13:53:08 -0600 Subject: [PATCH] Split out a foreground and background executor --- crates/ai2/src/auth.rs | 1 - .../ai2/src/providers/open_ai/completion.rs | 4 +- crates/ai2/src/providers/open_ai/embedding.rs | 52 ++++++++----------- crates/ai2/src/test.rs | 14 +++-- crates/call2/src/call2.rs | 4 +- crates/call2/src/room.rs | 9 ++-- crates/client2/src/client2.rs | 32 ++++++++---- crates/client2/src/telemetry.rs | 2 +- crates/copilot2/src/copilot2.rs | 12 ++--- crates/db2/src/db2.rs | 2 +- crates/gpui2/src/app.rs | 15 ++++-- crates/gpui2/src/app/model_context.rs | 28 +++++----- crates/gpui2/src/app/test_context.rs | 8 +-- crates/gpui2/src/assets.rs | 2 +- crates/gpui2/src/executor.rs | 2 +- crates/journal2/src/journal2.rs | 2 +- crates/language2/src/buffer.rs | 16 +++--- crates/language2/src/buffer_tests.rs | 10 ++-- crates/lsp2/src/lsp2.rs | 10 ++-- crates/prettier2/src/prettier2.rs | 2 +- crates/project2/src/lsp_command.rs | 24 ++++----- crates/project2/src/project2.rs | 24 ++++----- crates/project2/src/worktree.rs | 25 ++++----- crates/settings2/src/settings_file.rs | 5 +- crates/terminal2/src/terminal2.rs | 4 +- crates/zed2/src/main.rs | 6 +-- 26 files changed, 165 insertions(+), 150 deletions(-) diff --git a/crates/ai2/src/auth.rs b/crates/ai2/src/auth.rs index 2f689f2cda..995f20d39c 100644 --- a/crates/ai2/src/auth.rs +++ b/crates/ai2/src/auth.rs @@ -1,4 +1,3 @@ -use async_trait::async_trait; use gpui2::AppContext; #[derive(Clone, Debug)] diff --git a/crates/ai2/src/providers/open_ai/completion.rs b/crates/ai2/src/providers/open_ai/completion.rs index 840841a936..bf9dc704a2 100644 --- a/crates/ai2/src/providers/open_ai/completion.rs +++ b/crates/ai2/src/providers/open_ai/completion.rs @@ -1,5 +1,4 @@ use anyhow::{anyhow, Result}; -use async_trait::async_trait; use futures::{ future::BoxFuture, io::BufReader, stream::BoxStream, AsyncBufReadExt, AsyncReadExt, FutureExt, Stream, StreamExt, @@ -258,8 +257,7 @@ impl CredentialProvider for OpenAICompletionProvider { } fn delete_credentials(&self, cx: &mut AppContext) { - cx.run_on_main(move |cx| cx.delete_credentials(OPENAI_API_URL).log_err()) - .await; + cx.delete_credentials(OPENAI_API_URL).log_err(); *self.credential.write() = ProviderCredential::NoCredentials; } } diff --git a/crates/ai2/src/providers/open_ai/embedding.rs b/crates/ai2/src/providers/open_ai/embedding.rs index dde4af1273..27a01328f3 100644 --- a/crates/ai2/src/providers/open_ai/embedding.rs +++ b/crates/ai2/src/providers/open_ai/embedding.rs @@ -146,7 +146,6 @@ impl OpenAIEmbeddingProvider { } } -#[async_trait] impl CredentialProvider for OpenAIEmbeddingProvider { fn has_credentials(&self) -> bool { match *self.credential.read() { @@ -154,52 +153,45 @@ impl CredentialProvider for OpenAIEmbeddingProvider { _ => false, } } - async fn retrieve_credentials(&self, cx: &mut AppContext) -> ProviderCredential { + fn retrieve_credentials(&self, cx: &mut AppContext) -> ProviderCredential { let existing_credential = self.credential.read().clone(); - let retrieved_credential = cx - .run_on_main(move |cx| match existing_credential { - ProviderCredential::Credentials { .. } => { - return existing_credential.clone(); - } - _ => { - if let Some(api_key) = env::var("OPENAI_API_KEY").log_err() { - return ProviderCredential::Credentials { api_key }; - } - - if let Some(Some((_, api_key))) = cx.read_credentials(OPENAI_API_URL).log_err() - { - if let Some(api_key) = String::from_utf8(api_key).log_err() { - return ProviderCredential::Credentials { api_key }; - } else { - return ProviderCredential::NoCredentials; - } + let retrieved_credential = match existing_credential { + ProviderCredential::Credentials { .. } => existing_credential.clone(), + _ => { + if let Some(api_key) = env::var("OPENAI_API_KEY").log_err() { + ProviderCredential::Credentials { api_key } + } else if let Some(Some((_, api_key))) = + cx.read_credentials(OPENAI_API_URL).log_err() + { + if let Some(api_key) = String::from_utf8(api_key).log_err() { + ProviderCredential::Credentials { api_key } } else { - return ProviderCredential::NoCredentials; + ProviderCredential::NoCredentials } + } else { + ProviderCredential::NoCredentials } - }) - .await; + } + }; *self.credential.write() = retrieved_credential.clone(); retrieved_credential } - async fn save_credentials(&self, cx: &mut AppContext, credential: ProviderCredential) { + fn save_credentials(&self, cx: &mut AppContext, credential: ProviderCredential) { *self.credential.write() = credential.clone(); - let credential = credential.clone(); - cx.run_on_main(move |cx| match credential { + match credential { ProviderCredential::Credentials { api_key } => { cx.write_credentials(OPENAI_API_URL, "Bearer", api_key.as_bytes()) .log_err(); } _ => {} - }) - .await; + } } - async fn delete_credentials(&self, cx: &mut AppContext) { - cx.run_on_main(move |cx| cx.delete_credentials(OPENAI_API_URL).log_err()) - .await; + + fn delete_credentials(&self, cx: &mut AppContext) { + cx.delete_credentials(OPENAI_API_URL).log_err(); *self.credential.write() = ProviderCredential::NoCredentials; } } diff --git a/crates/ai2/src/test.rs b/crates/ai2/src/test.rs index ee88529aec..b061a47139 100644 --- a/crates/ai2/src/test.rs +++ b/crates/ai2/src/test.rs @@ -100,16 +100,15 @@ impl FakeEmbeddingProvider { } } -#[async_trait] impl CredentialProvider for FakeEmbeddingProvider { fn has_credentials(&self) -> bool { true } - async fn retrieve_credentials(&self, _cx: &mut AppContext) -> ProviderCredential { + fn retrieve_credentials(&self, _cx: &mut AppContext) -> ProviderCredential { ProviderCredential::NotNeeded } - async fn save_credentials(&self, _cx: &mut AppContext, _credential: ProviderCredential) {} - async fn delete_credentials(&self, _cx: &mut AppContext) {} + fn save_credentials(&self, _cx: &mut AppContext, _credential: ProviderCredential) {} + fn delete_credentials(&self, _cx: &mut AppContext) {} } #[async_trait] @@ -162,16 +161,15 @@ impl FakeCompletionProvider { } } -#[async_trait] impl CredentialProvider for FakeCompletionProvider { fn has_credentials(&self) -> bool { true } - async fn retrieve_credentials(&self, _cx: &mut AppContext) -> ProviderCredential { + fn retrieve_credentials(&self, _cx: &mut AppContext) -> ProviderCredential { ProviderCredential::NotNeeded } - async fn save_credentials(&self, _cx: &mut AppContext, _credential: ProviderCredential) {} - async fn delete_credentials(&self, _cx: &mut AppContext) {} + fn save_credentials(&self, _cx: &mut AppContext, _credential: ProviderCredential) {} + fn delete_credentials(&self, _cx: &mut AppContext) {} } impl CompletionProvider for FakeCompletionProvider { diff --git a/crates/call2/src/call2.rs b/crates/call2/src/call2.rs index fd09dc3180..9383f9845f 100644 --- a/crates/call2/src/call2.rs +++ b/crates/call2/src/call2.rs @@ -196,7 +196,7 @@ impl ActiveCall { }) .shared(); self.pending_room_creation = Some(room.clone()); - cx.executor().spawn(async move { + cx.background_executor().spawn(async move { room.await.map_err(|err| anyhow!("{:?}", err))?; anyhow::Ok(()) }) @@ -230,7 +230,7 @@ impl ActiveCall { }; let client = self.client.clone(); - cx.executor().spawn(async move { + cx.background_executor().spawn(async move { client .request(proto::CancelCall { room_id, diff --git a/crates/call2/src/room.rs b/crates/call2/src/room.rs index 556f9e778e..f44bdd35b5 100644 --- a/crates/call2/src/room.rs +++ b/crates/call2/src/room.rs @@ -322,7 +322,7 @@ impl Room { fn app_will_quit(&mut self, cx: &mut ModelContext) -> impl Future { let task = if self.status.is_online() { let leave = self.leave_internal(cx); - Some(cx.executor().spawn(async move { + Some(cx.background_executor().spawn(async move { leave.await.log_err(); })) } else { @@ -390,7 +390,7 @@ impl Room { self.clear_state(cx); let leave_room = self.client.request(proto::LeaveRoom {}); - cx.executor().spawn(async move { + cx.background_executor().spawn(async move { leave_room.await?; anyhow::Ok(()) }) @@ -1202,7 +1202,7 @@ impl Room { }; cx.notify(); - cx.executor().spawn_on_main(move || async move { + cx.background_executor().spawn(async move { client .request(proto::UpdateParticipantLocation { room_id, @@ -1569,7 +1569,8 @@ impl LiveKitRoom { *muted = should_mute; cx.notify(); Ok(( - cx.executor().spawn(track_publication.set_mute(*muted)), + cx.background_executor() + .spawn(track_publication.set_mute(*muted)), old_muted, )) } diff --git a/crates/client2/src/client2.rs b/crates/client2/src/client2.rs index 50a6bf1632..b933b62a6f 100644 --- a/crates/client2/src/client2.rs +++ b/crates/client2/src/client2.rs @@ -234,12 +234,14 @@ struct ClientState { message_handlers: HashMap< TypeId, Arc< - dyn Fn( - AnyModel, - Box, - &Arc, - AsyncAppContext, - ) -> LocalBoxFuture<'static, Result<()>>, + dyn Send + + Sync + + Fn( + AnyModel, + Box, + &Arc, + AsyncAppContext, + ) -> LocalBoxFuture<'static, Result<()>>, >, >, } @@ -551,7 +553,11 @@ impl Client { where M: EnvelopedMessage, E: 'static, - H: 'static + Sync + Fn(Model, TypedEnvelope, Arc, AsyncAppContext) -> F, + H: 'static + + Sync + + Fn(Model, TypedEnvelope, Arc, AsyncAppContext) -> F + + Send + + Sync, F: 'static + Future>, { let message_type_id = TypeId::of::(); @@ -593,7 +599,11 @@ impl Client { where M: RequestMessage, E: 'static, - H: 'static + Sync + Fn(Model, TypedEnvelope, Arc, AsyncAppContext) -> F, + H: 'static + + Sync + + Fn(Model, TypedEnvelope, Arc, AsyncAppContext) -> F + + Send + + Sync, F: 'static + Future>, { self.add_message_handler(model, move |handle, envelope, this, cx| { @@ -609,7 +619,7 @@ impl Client { where M: EntityMessage, E: 'static, - H: 'static + Fn(Model, TypedEnvelope, Arc, AsyncAppContext) -> F, + H: 'static + Fn(Model, TypedEnvelope, Arc, AsyncAppContext) -> F + Send + Sync, F: 'static + Future>, { self.add_entity_message_handler::(move |subscriber, message, client, cx| { @@ -621,7 +631,7 @@ impl Client { where M: EntityMessage, E: 'static, - H: 'static + Fn(AnyModel, TypedEnvelope, Arc, AsyncAppContext) -> F, + H: 'static + Fn(AnyModel, TypedEnvelope, Arc, AsyncAppContext) -> F + Send + Sync, F: 'static + Future>, { let model_type_id = TypeId::of::(); @@ -660,7 +670,7 @@ impl Client { where M: EntityMessage + RequestMessage, E: 'static, - H: 'static + Fn(Model, TypedEnvelope, Arc, AsyncAppContext) -> F, + H: 'static + Fn(Model, TypedEnvelope, Arc, AsyncAppContext) -> F + Send + Sync, F: 'static + Future>, { self.add_model_message_handler(move |entity, envelope, client, cx| { diff --git a/crates/client2/src/telemetry.rs b/crates/client2/src/telemetry.rs index 7fa57f9fb6..0ef5f0d140 100644 --- a/crates/client2/src/telemetry.rs +++ b/crates/client2/src/telemetry.rs @@ -123,7 +123,7 @@ impl Telemetry { // TODO: Replace all hardware stuff with nested SystemSpecs json let this = Arc::new(Self { http_client: client, - executor: cx.executor().clone(), + executor: cx.background_executor().clone(), state: Mutex::new(TelemetryState { app_metadata: cx.app_metadata(), architecture: env::consts::ARCH, diff --git a/crates/copilot2/src/copilot2.rs b/crates/copilot2/src/copilot2.rs index 3d50834e94..3b059775cd 100644 --- a/crates/copilot2/src/copilot2.rs +++ b/crates/copilot2/src/copilot2.rs @@ -535,7 +535,7 @@ impl Copilot { } }; - cx.executor() + cx.background_executor() .spawn(task.map_err(|err| anyhow!("{:?}", err))) } else { // If we're downloading, wait until download is finished @@ -549,7 +549,7 @@ impl Copilot { self.update_sign_in_status(request::SignInStatus::NotSignedIn, cx); if let CopilotServer::Running(RunningCopilotServer { lsp: server, .. }) = &self.server { let server = server.clone(); - cx.executor().spawn(async move { + cx.background_executor().spawn(async move { server .request::(request::SignOutParams {}) .await?; @@ -579,7 +579,7 @@ impl Copilot { cx.notify(); - cx.executor().spawn(start_task) + cx.background_executor().spawn(start_task) } pub fn language_server(&self) -> Option<(&LanguageServerName, &Arc)> { @@ -760,7 +760,7 @@ impl Copilot { .request::(request::NotifyAcceptedParams { uuid: completion.uuid.clone(), }); - cx.executor().spawn(async move { + cx.background_executor().spawn(async move { request.await?; Ok(()) }) @@ -784,7 +784,7 @@ impl Copilot { .map(|completion| completion.uuid.clone()) .collect(), }); - cx.executor().spawn(async move { + cx.background_executor().spawn(async move { request.await?; Ok(()) }) @@ -827,7 +827,7 @@ impl Copilot { .map(|file| file.path().to_path_buf()) .unwrap_or_default(); - cx.executor().spawn(async move { + cx.background_executor().spawn(async move { let (version, snapshot) = snapshot.await?; let result = lsp .request::(request::GetCompletionsParams { diff --git a/crates/db2/src/db2.rs b/crates/db2/src/db2.rs index e2e1ae9eaa..fe79dfbb0c 100644 --- a/crates/db2/src/db2.rs +++ b/crates/db2/src/db2.rs @@ -185,7 +185,7 @@ pub fn write_and_log(cx: &mut AppContext, db_write: impl FnOnce() -> F + Send where F: Future> + Send, { - cx.executor() + cx.background_executor() .spawn(async move { db_write().await.log_err() }) .detach() } diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index 3ab2d8c1f8..265ce59a02 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -21,7 +21,7 @@ use crate::{ }; use anyhow::{anyhow, Result}; use collections::{HashMap, HashSet, VecDeque}; -use futures::{future::BoxFuture, Future}; +use futures::{future::LocalBoxFuture, Future}; use parking_lot::Mutex; use slotmap::SlotMap; use std::{ @@ -101,6 +101,10 @@ impl App { self.0.borrow().background_executor.clone() } + pub fn foreground_executor(&self) -> ForegroundExecutor { + self.0.borrow().foreground_executor.clone() + } + pub fn text_system(&self) -> Arc { self.0.borrow().text_system.clone() } @@ -110,7 +114,7 @@ type ActionBuilder = fn(json: Option) -> anyhow::Result; type Handler = Box bool + 'static>; type Listener = Box bool + 'static>; -type QuitHandler = Box BoxFuture<'static, ()> + 'static>; +type QuitHandler = Box LocalBoxFuture<'static, ()> + 'static>; type ReleaseListener = Box; pub struct AppContext { @@ -535,10 +539,15 @@ impl AppContext { } /// Obtains a reference to the executor, which can be used to spawn futures. - pub fn executor(&self) -> &BackgroundExecutor { + pub fn background_executor(&self) -> &BackgroundExecutor { &self.background_executor } + /// Obtains a reference to the executor, which can be used to spawn futures. + pub fn foreground_executor(&self) -> &ForegroundExecutor { + &self.foreground_executor + } + /// Spawns the future returned by the given function on the thread pool. The closure will be invoked /// with AsyncAppContext, which allows the application state to be accessed across await points. pub fn spawn(&self, f: impl FnOnce(AsyncAppContext) -> Fut) -> Task diff --git a/crates/gpui2/src/app/model_context.rs b/crates/gpui2/src/app/model_context.rs index f0fc1f07f0..ee8c8871e6 100644 --- a/crates/gpui2/src/app/model_context.rs +++ b/crates/gpui2/src/app/model_context.rs @@ -43,10 +43,10 @@ impl<'a, T: 'static> ModelContext<'a, T> { pub fn observe( &mut self, entity: &E, - mut on_notify: impl FnMut(&mut T, E, &mut ModelContext<'_, T>) + Send + 'static, + mut on_notify: impl FnMut(&mut T, E, &mut ModelContext<'_, T>) + 'static, ) -> Subscription where - T: 'static + Send, + T: 'static, T2: 'static, E: Entity, { @@ -69,10 +69,10 @@ impl<'a, T: 'static> ModelContext<'a, T> { pub fn subscribe( &mut self, entity: &E, - mut on_event: impl FnMut(&mut T, E, &T2::Event, &mut ModelContext<'_, T>) + Send + 'static, + mut on_event: impl FnMut(&mut T, E, &T2::Event, &mut ModelContext<'_, T>) + 'static, ) -> Subscription where - T: 'static + Send, + T: 'static, T2: 'static + EventEmitter, E: Entity, { @@ -95,7 +95,7 @@ impl<'a, T: 'static> ModelContext<'a, T> { pub fn on_release( &mut self, - mut on_release: impl FnMut(&mut T, &mut AppContext) + Send + 'static, + mut on_release: impl FnMut(&mut T, &mut AppContext) + 'static, ) -> Subscription where T: 'static, @@ -112,10 +112,10 @@ impl<'a, T: 'static> ModelContext<'a, T> { pub fn observe_release( &mut self, entity: &E, - mut on_release: impl FnMut(&mut T, &mut T2, &mut ModelContext<'_, T>) + Send + 'static, + mut on_release: impl FnMut(&mut T, &mut T2, &mut ModelContext<'_, T>) + 'static, ) -> Subscription where - T: Any + Send, + T: Any, T2: 'static, E: Entity, { @@ -134,10 +134,10 @@ impl<'a, T: 'static> ModelContext<'a, T> { pub fn observe_global( &mut self, - mut f: impl FnMut(&mut T, &mut ModelContext<'_, T>) + Send + 'static, + mut f: impl FnMut(&mut T, &mut ModelContext<'_, T>) + 'static, ) -> Subscription where - T: 'static + Send, + T: 'static, { let handle = self.weak_model(); self.global_observers.insert( @@ -148,11 +148,11 @@ impl<'a, T: 'static> ModelContext<'a, T> { pub fn on_app_quit( &mut self, - mut on_quit: impl FnMut(&mut T, &mut ModelContext) -> Fut + Send + 'static, + mut on_quit: impl FnMut(&mut T, &mut ModelContext) -> Fut + 'static, ) -> Subscription where - Fut: 'static + Future + Send, - T: 'static + Send, + Fut: 'static + Future, + T: 'static, { let handle = self.weak_model(); self.app.quit_observers.insert( @@ -164,7 +164,7 @@ impl<'a, T: 'static> ModelContext<'a, T> { future.await; } } - .boxed() + .boxed_local() }), ) } @@ -183,7 +183,7 @@ impl<'a, T: 'static> ModelContext<'a, T> { pub fn update_global(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R where - G: 'static + Send, + G: 'static, { let mut global = self.app.lease_global::(); let result = f(&mut global, self); diff --git a/crates/gpui2/src/app/test_context.rs b/crates/gpui2/src/app/test_context.rs index e3bf8eb7da..624ec67eac 100644 --- a/crates/gpui2/src/app/test_context.rs +++ b/crates/gpui2/src/app/test_context.rs @@ -135,18 +135,20 @@ impl TestAppContext { } } - pub fn subscribe( + pub fn subscribe( &mut self, entity: &Model, ) -> futures::channel::mpsc::UnboundedReceiver where - T::Event: 'static + Send + Clone, + T::Event: 'static + Clone, { let (mut tx, rx) = futures::channel::mpsc::unbounded(); entity .update(self, |_, cx: &mut ModelContext| { cx.subscribe(entity, move |_, _, event, cx| { - cx.executor().block(tx.send(event.clone())).unwrap(); + cx.background_executor() + .block(tx.send(event.clone())) + .unwrap(); }) }) .detach(); diff --git a/crates/gpui2/src/assets.rs b/crates/gpui2/src/assets.rs index 0437b3d6de..39c8562b69 100644 --- a/crates/gpui2/src/assets.rs +++ b/crates/gpui2/src/assets.rs @@ -8,7 +8,7 @@ use std::{ sync::atomic::{AtomicUsize, Ordering::SeqCst}, }; -pub trait AssetSource: 'static + Sync { +pub trait AssetSource: 'static + Send + Sync { fn load(&self, path: &str) -> Result>; fn list(&self, path: &str) -> Result>; } diff --git a/crates/gpui2/src/executor.rs b/crates/gpui2/src/executor.rs index d0b65fa10e..5a04cf40f0 100644 --- a/crates/gpui2/src/executor.rs +++ b/crates/gpui2/src/executor.rs @@ -53,7 +53,7 @@ where E: 'static + Send + Debug, { pub fn detach_and_log_err(self, cx: &mut AppContext) { - cx.executor().spawn(self.log_err()).detach(); + cx.background_executor().spawn(self.log_err()).detach(); } } diff --git a/crates/journal2/src/journal2.rs b/crates/journal2/src/journal2.rs index 6268548530..d875cb3834 100644 --- a/crates/journal2/src/journal2.rs +++ b/crates/journal2/src/journal2.rs @@ -77,7 +77,7 @@ pub fn new_journal_entry(_: Arc, cx: &mut AppContext) { let now = now.time(); let _entry_heading = heading_entry(now, &settings.hour_format); - let _create_entry = cx.executor().spawn(async move { + let _create_entry = cx.background_executor().spawn(async move { std::fs::create_dir_all(month_dir)?; OpenOptions::new() .create(true) diff --git a/crates/language2/src/buffer.rs b/crates/language2/src/buffer.rs index 3ab68d9f44..d8e0149460 100644 --- a/crates/language2/src/buffer.rs +++ b/crates/language2/src/buffer.rs @@ -652,7 +652,7 @@ impl Buffer { if !self.is_dirty() { let reload = self.reload(cx).log_err().map(drop); - task = cx.executor().spawn(reload); + task = cx.background_executor().spawn(reload); } } } @@ -684,7 +684,7 @@ impl Buffer { let snapshot = self.snapshot(); let mut diff = self.git_diff.clone(); - let diff = cx.executor().spawn(async move { + let diff = cx.background_executor().spawn(async move { diff.update(&diff_base, &snapshot).await; diff }); @@ -793,7 +793,7 @@ impl Buffer { let mut syntax_snapshot = syntax_map.snapshot(); drop(syntax_map); - let parse_task = cx.executor().spawn({ + let parse_task = cx.background_executor().spawn({ let language = language.clone(); let language_registry = language_registry.clone(); async move { @@ -803,7 +803,7 @@ impl Buffer { }); match cx - .executor() + .background_executor() .block_with_timeout(self.sync_parse_timeout, parse_task) { Ok(new_syntax_snapshot) => { @@ -866,9 +866,9 @@ impl Buffer { fn request_autoindent(&mut self, cx: &mut ModelContext) { if let Some(indent_sizes) = self.compute_autoindents() { - let indent_sizes = cx.executor().spawn(indent_sizes); + let indent_sizes = cx.background_executor().spawn(indent_sizes); match cx - .executor() + .background_executor() .block_with_timeout(Duration::from_micros(500), indent_sizes) { Ok(indent_sizes) => self.apply_autoindents(indent_sizes, cx), @@ -1117,7 +1117,7 @@ impl Buffer { pub fn diff(&self, mut new_text: String, cx: &AppContext) -> Task { let old_text = self.as_rope().clone(); let base_version = self.version(); - cx.executor().spawn(async move { + cx.background_executor().spawn(async move { let old_text = old_text.to_string(); let line_ending = LineEnding::detect(&new_text); LineEnding::normalize(&mut new_text); @@ -1155,7 +1155,7 @@ impl Buffer { let old_text = self.as_rope().clone(); let line_ending = self.line_ending(); let base_version = self.version(); - cx.executor().spawn(async move { + cx.background_executor().spawn(async move { let ranges = trailing_whitespace_ranges(&old_text); let empty = Arc::::from(""); Diff { diff --git a/crates/language2/src/buffer_tests.rs b/crates/language2/src/buffer_tests.rs index d2d886dd84..2012509878 100644 --- a/crates/language2/src/buffer_tests.rs +++ b/crates/language2/src/buffer_tests.rs @@ -559,7 +559,7 @@ async fn test_outline(cx: &mut gpui2::TestAppContext) { cx: &'a gpui2::TestAppContext, ) -> Vec<(&'a str, Vec)> { let matches = cx - .update(|cx| outline.search(query, cx.executor().clone())) + .update(|cx| outline.search(query, cx.background_executor().clone())) .await; matches .into_iter() @@ -1879,7 +1879,7 @@ fn test_serialization(cx: &mut gpui2::AppContext) { let state = buffer1.read(cx).to_proto(); let ops = cx - .executor() + .background_executor() .block(buffer1.read(cx).serialize_ops(None, cx)); let buffer2 = cx.build_model(|cx| { let mut buffer = Buffer::from_proto(1, state, None).unwrap(); @@ -1921,7 +1921,7 @@ fn test_random_collaboration(cx: &mut AppContext, mut rng: StdRng) { let buffer = cx.build_model(|cx| { let state = base_buffer.read(cx).to_proto(); let ops = cx - .executor() + .background_executor() .block(base_buffer.read(cx).serialize_ops(None, cx)); let mut buffer = Buffer::from_proto(i as ReplicaId, state, None).unwrap(); buffer @@ -2025,7 +2025,9 @@ fn test_random_collaboration(cx: &mut AppContext, mut rng: StdRng) { } 50..=59 if replica_ids.len() < max_peers => { let old_buffer_state = buffer.read(cx).to_proto(); - let old_buffer_ops = cx.executor().block(buffer.read(cx).serialize_ops(None, cx)); + let old_buffer_ops = cx + .background_executor() + .block(buffer.read(cx).serialize_ops(None, cx)); let new_replica_id = (0..=replica_ids.len() as ReplicaId) .filter(|replica_id| *replica_id != buffer.read(cx).replica_id()) .choose(&mut rng) diff --git a/crates/lsp2/src/lsp2.rs b/crates/lsp2/src/lsp2.rs index 120e749d19..ed67a5c9c2 100644 --- a/crates/lsp2/src/lsp2.rs +++ b/crates/lsp2/src/lsp2.rs @@ -595,8 +595,8 @@ impl LanguageServer { where T: request::Request, T::Params: 'static + Send, - F: 'static + Send + FnMut(T::Params, AsyncAppContext) -> Fut, - Fut: 'static + Future> + Send, + F: 'static + FnMut(T::Params, AsyncAppContext) -> Fut + Send, + Fut: 'static + Future>, { self.on_custom_request(T::METHOD, f) } @@ -629,7 +629,7 @@ impl LanguageServer { #[must_use] pub fn on_custom_notification(&self, method: &'static str, mut f: F) -> Subscription where - F: 'static + Send + FnMut(Params, AsyncAppContext), + F: 'static + FnMut(Params, AsyncAppContext) + Send, Params: DeserializeOwned, { let prev_handler = self.notification_handlers.lock().insert( @@ -657,8 +657,8 @@ impl LanguageServer { mut f: F, ) -> Subscription where - F: 'static + Send + FnMut(Params, AsyncAppContext) -> Fut, - Fut: 'static + Future> + Send, + F: 'static + FnMut(Params, AsyncAppContext) -> Fut + Send, + Fut: 'static + Future>, Params: DeserializeOwned + Send + 'static, Res: Serialize, { diff --git a/crates/prettier2/src/prettier2.rs b/crates/prettier2/src/prettier2.rs index a71bf1a8b0..6d9664b234 100644 --- a/crates/prettier2/src/prettier2.rs +++ b/crates/prettier2/src/prettier2.rs @@ -143,7 +143,7 @@ impl Prettier { ) -> anyhow::Result { use lsp2::LanguageServerBinary; - let executor = cx.executor().clone(); + let executor = cx.background_executor().clone(); anyhow::ensure!( prettier_dir.is_dir(), "Prettier dir {prettier_dir:?} is not a directory" diff --git a/crates/project2/src/lsp_command.rs b/crates/project2/src/lsp_command.rs index 84a6c0517c..9e6a96e15e 100644 --- a/crates/project2/src/lsp_command.rs +++ b/crates/project2/src/lsp_command.rs @@ -32,7 +32,7 @@ pub fn lsp_formatting_options(tab_size: u32) -> lsp2::FormattingOptions { } } -#[async_trait] +#[async_trait(?Send)] pub(crate) trait LspCommand: 'static + Sized + Send { type Response: 'static + Default + Send; type LspRequest: 'static + Send + lsp2::request::Request; @@ -148,7 +148,7 @@ impl From for FormattingOptions { } } -#[async_trait] +#[async_trait(?Send)] impl LspCommand for PrepareRename { type Response = Option>; type LspRequest = lsp2::request::PrepareRenameRequest; @@ -279,7 +279,7 @@ impl LspCommand for PrepareRename { } } -#[async_trait] +#[async_trait(?Send)] impl LspCommand for PerformRename { type Response = ProjectTransaction; type LspRequest = lsp2::request::Rename; @@ -398,7 +398,7 @@ impl LspCommand for PerformRename { } } -#[async_trait] +#[async_trait(?Send)] impl LspCommand for GetDefinition { type Response = Vec; type LspRequest = lsp2::request::GotoDefinition; @@ -491,7 +491,7 @@ impl LspCommand for GetDefinition { } } -#[async_trait] +#[async_trait(?Send)] impl LspCommand for GetTypeDefinition { type Response = Vec; type LspRequest = lsp2::request::GotoTypeDefinition; @@ -783,7 +783,7 @@ fn location_links_to_proto( .collect() } -#[async_trait] +#[async_trait(?Send)] impl LspCommand for GetReferences { type Response = Vec; type LspRequest = lsp2::request::References; @@ -945,7 +945,7 @@ impl LspCommand for GetReferences { } } -#[async_trait] +#[async_trait(?Send)] impl LspCommand for GetDocumentHighlights { type Response = Vec; type LspRequest = lsp2::request::DocumentHighlightRequest; @@ -1096,7 +1096,7 @@ impl LspCommand for GetDocumentHighlights { } } -#[async_trait] +#[async_trait(?Send)] impl LspCommand for GetHover { type Response = Option; type LspRequest = lsp2::request::HoverRequest; @@ -1314,7 +1314,7 @@ impl LspCommand for GetHover { } } -#[async_trait] +#[async_trait(?Send)] impl LspCommand for GetCompletions { type Response = Vec; type LspRequest = lsp2::request::Completion; @@ -1545,7 +1545,7 @@ impl LspCommand for GetCompletions { } } -#[async_trait] +#[async_trait(?Send)] impl LspCommand for GetCodeActions { type Response = Vec; type LspRequest = lsp2::request::CodeActionRequest; @@ -1684,7 +1684,7 @@ impl LspCommand for GetCodeActions { } } -#[async_trait] +#[async_trait(?Send)] impl LspCommand for OnTypeFormatting { type Response = Option; type LspRequest = lsp2::request::OnTypeFormatting; @@ -2192,7 +2192,7 @@ impl InlayHints { } } -#[async_trait] +#[async_trait(?Send)] impl LspCommand for InlayHints { type Response = Vec; type LspRequest = lsp2::InlayHintRequest; diff --git a/crates/project2/src/project2.rs b/crates/project2/src/project2.rs index 748e619e96..1457bd41cc 100644 --- a/crates/project2/src/project2.rs +++ b/crates/project2/src/project2.rs @@ -1758,7 +1758,7 @@ impl Project { } }; - cx.executor().spawn(async move { + cx.background_executor().spawn(async move { wait_for_loading_buffer(loading_watch) .await .map_err(|error| anyhow!("{}", error)) @@ -5593,7 +5593,7 @@ impl Project { }) .collect::>(); - let background = cx.executor().clone(); + let background = cx.background_executor().clone(); let path_count: usize = snapshots.iter().map(|s| s.visible_file_count()).sum(); if path_count == 0 { let (_, rx) = smol::channel::bounded(1024); @@ -5616,11 +5616,11 @@ impl Project { } }) .collect(); - cx.executor() + cx.background_executor() .spawn(Self::background_search( unnamed_files, opened_buffers, - cx.executor().clone(), + cx.background_executor().clone(), self.fs.clone(), workers, query.clone(), @@ -5631,9 +5631,9 @@ impl Project { .detach(); let (buffers, buffers_rx) = Self::sort_candidates_and_open_buffers(matching_paths_rx, cx); - let background = cx.executor().clone(); + let background = cx.background_executor().clone(); let (result_tx, result_rx) = smol::channel::bounded(1024); - cx.executor() + cx.background_executor() .spawn(async move { let Ok(buffers) = buffers.await else { return; @@ -5993,7 +5993,7 @@ impl Project { Task::ready(Ok((tree, relative_path))) } else { let worktree = self.create_local_worktree(abs_path, visible, cx); - cx.executor() + cx.background_executor() .spawn(async move { Ok((worktree.await?, PathBuf::new())) }) } } @@ -6064,7 +6064,7 @@ impl Project { .shared() }) .clone(); - cx.executor().spawn(async move { + cx.background_executor().spawn(async move { match task.await { Ok(worktree) => Ok(worktree), Err(err) => Err(anyhow!("{}", err)), @@ -6519,7 +6519,7 @@ impl Project { }) .collect::>(); - cx.executor() + cx.background_executor() .spawn(async move { for task_result in future::join_all(prettiers_to_reload.into_iter().map(|(worktree_id, prettier_path, prettier_task)| { async move { @@ -7358,7 +7358,7 @@ impl Project { }) .log_err(); - cx.executor() + cx.background_executor() .spawn( async move { let operations = operations.await; @@ -7960,7 +7960,7 @@ impl Project { if let Some(buffer) = this.buffer_for_id(buffer_id) { let operations = buffer.read(cx).serialize_ops(Some(remote_version), cx); - cx.executor().spawn(async move { + cx.background_executor().spawn(async move { let operations = operations.await; for chunk in split_operations(operations) { client @@ -8198,7 +8198,7 @@ impl Project { cx: &mut ModelContext, ) -> Task, String)>>> { let snapshot = self.buffer_snapshot_for_lsp_version(buffer, server_id, version, cx); - cx.executor().spawn(async move { + cx.background_executor().spawn(async move { let snapshot = snapshot?; let mut lsp_edits = lsp_edits .into_iter() diff --git a/crates/project2/src/worktree.rs b/crates/project2/src/worktree.rs index dd90df81b3..2718b5d8f0 100644 --- a/crates/project2/src/worktree.rs +++ b/crates/project2/src/worktree.rs @@ -365,10 +365,10 @@ impl Worktree { }) .detach(); - let background_scanner_task = cx.executor().spawn({ + let background_scanner_task = cx.background_executor().spawn({ let fs = fs.clone(); let snapshot = snapshot.clone(); - let background = cx.executor().clone(); + let background = cx.background_executor().clone(); async move { let events = fs.watch(&abs_path, Duration::from_millis(100)).await; BackgroundScanner::new( @@ -429,7 +429,7 @@ impl Worktree { let background_snapshot = Arc::new(Mutex::new(snapshot.clone())); let (mut snapshot_updated_tx, mut snapshot_updated_rx) = watch::channel(); - cx.executor() + cx.background_executor() .spawn({ let background_snapshot = background_snapshot.clone(); async move { @@ -1008,7 +1008,7 @@ impl LocalWorktree { let lowest_ancestor = self.lowest_ancestor(&path); let abs_path = self.absolutize(&path); let fs = self.fs.clone(); - let write = cx.executor().spawn(async move { + let write = cx.background_executor().spawn(async move { if is_dir { fs.create_dir(&abs_path).await } else { @@ -1058,7 +1058,7 @@ impl LocalWorktree { let abs_path = self.absolutize(&path); let fs = self.fs.clone(); let write = cx - .executor() + .background_executor() .spawn(async move { fs.save(&abs_path, &text, line_ending).await }); cx.spawn(|this, mut cx| async move { @@ -1079,7 +1079,7 @@ impl LocalWorktree { let abs_path = self.absolutize(&entry.path); let fs = self.fs.clone(); - let delete = cx.executor().spawn(async move { + let delete = cx.background_executor().spawn(async move { if entry.is_file() { fs.remove_file(&abs_path, Default::default()).await?; } else { @@ -1119,7 +1119,7 @@ impl LocalWorktree { let abs_old_path = self.absolutize(&old_path); let abs_new_path = self.absolutize(&new_path); let fs = self.fs.clone(); - let rename = cx.executor().spawn(async move { + let rename = cx.background_executor().spawn(async move { fs.rename(&abs_old_path, &abs_new_path, Default::default()) .await }); @@ -1146,7 +1146,7 @@ impl LocalWorktree { let abs_old_path = self.absolutize(&old_path); let abs_new_path = self.absolutize(&new_path); let fs = self.fs.clone(); - let copy = cx.executor().spawn(async move { + let copy = cx.background_executor().spawn(async move { copy_recursive( fs.as_ref(), &abs_old_path, @@ -1174,7 +1174,7 @@ impl LocalWorktree { ) -> Option>> { let path = self.entry_for_id(entry_id)?.path.clone(); let mut refresh = self.refresh_entries_for_paths(vec![path]); - Some(cx.executor().spawn(async move { + Some(cx.background_executor().spawn(async move { refresh.next().await; Ok(()) })) @@ -1248,7 +1248,7 @@ impl LocalWorktree { .ok(); let worktree_id = cx.entity_id().as_u64(); - let _maintain_remote_snapshot = cx.executor().spawn(async move { + let _maintain_remote_snapshot = cx.background_executor().spawn(async move { let mut is_first = true; while let Some((snapshot, entry_changes, repo_changes)) = snapshots_rx.next().await { let update; @@ -1306,7 +1306,7 @@ impl LocalWorktree { let rx = self.observe_updates(project_id, cx, move |update| { client.request(update).map(|result| result.is_ok()) }); - cx.executor() + cx.background_executor() .spawn(async move { rx.await.map_err(|_| anyhow!("share ended")) }) } @@ -2672,7 +2672,8 @@ impl language2::LocalFile for File { let worktree = self.worktree.read(cx).as_local().unwrap(); let abs_path = worktree.absolutize(&self.path); let fs = worktree.fs.clone(); - cx.executor().spawn(async move { fs.load(&abs_path).await }) + cx.background_executor() + .spawn(async move { fs.load(&abs_path).await }) } fn buffer_reloaded( diff --git a/crates/settings2/src/settings_file.rs b/crates/settings2/src/settings_file.rs index c3903c1c22..002c9daf12 100644 --- a/crates/settings2/src/settings_file.rs +++ b/crates/settings2/src/settings_file.rs @@ -63,7 +63,10 @@ pub fn handle_settings_file_changes( mut user_settings_file_rx: mpsc::UnboundedReceiver, cx: &mut AppContext, ) { - let user_settings_content = cx.executor().block(user_settings_file_rx.next()).unwrap(); + let user_settings_content = cx + .background_executor() + .block(user_settings_file_rx.next()) + .unwrap(); cx.update_global(|store: &mut SettingsStore, cx| { store .set_user_settings(&user_settings_content, cx) diff --git a/crates/terminal2/src/terminal2.rs b/crates/terminal2/src/terminal2.rs index b683fd5b51..adc5dd3511 100644 --- a/crates/terminal2/src/terminal2.rs +++ b/crates/terminal2/src/terminal2.rs @@ -984,7 +984,7 @@ impl Terminal { term.lock_unfair() //It's been too long, force block } else if let None = self.sync_task { //Skip this frame - let delay = cx.executor().timer(Duration::from_millis(16)); + let delay = cx.background_executor().timer(Duration::from_millis(16)); self.sync_task = Some(cx.spawn(|weak_handle, mut cx| async move { delay.await; if let Some(handle) = weak_handle.upgrade() { @@ -1302,7 +1302,7 @@ impl Terminal { cx: &mut ModelContext, ) -> Task>> { let term = self.term.clone(); - cx.executor().spawn(async move { + cx.background_executor().spawn(async move { let term = term.lock(); all_search_matches(&term, &searcher).collect() diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index 20b14a249a..1233bee327 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -117,7 +117,7 @@ fn main() { let client = client2::Client::new(http.clone(), cx); let mut languages = LanguageRegistry::new(login_shell_env_loaded); let copilot_language_server_id = languages.next_language_server_id(); - languages.set_executor(cx.executor().clone()); + languages.set_executor(cx.background_executor().clone()); languages.set_language_server_download_dir(paths::LANGUAGES_DIR.clone()); let languages = Arc::new(languages); let node_runtime = RealNodeRuntime::new(http.clone()); @@ -514,7 +514,7 @@ fn init_panic_hook(app: &App, installation_id: Option, session_id: Strin fn upload_previous_panics(http: Arc, cx: &mut AppContext) { let telemetry_settings = *client2::TelemetrySettings::get_global(cx); - cx.executor() + cx.background_executor() .spawn(async move { let panic_report_url = format!("{}/api/panic", &*client2::ZED_SERVER_URL); let mut children = smol::fs::read_dir(&*paths::LOGS_DIR).await?; @@ -644,7 +644,7 @@ fn load_embedded_fonts(cx: &AppContext) { let asset_source = cx.asset_source(); let font_paths = asset_source.list("fonts").unwrap(); let embedded_fonts = Mutex::new(Vec::new()); - let executor = cx.executor(); + let executor = cx.background_executor(); executor.block(executor.scoped(|scope| { for font_path in &font_paths {