From f3a0a11fc5f45a1267315389f0ac3507cebf5f75 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 13 Apr 2021 14:51:49 -0600 Subject: [PATCH] WIP --- Cargo.lock | 128 +++++++++++++++++++++++++++++++++++ zed/Cargo.toml | 1 + zed/src/lib.rs | 1 + zed/src/worktree/worktree.rs | 63 +++++++++-------- 4 files changed, 163 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 68b6460eab..15558eaa3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -199,6 +199,15 @@ name = "async-task" version = "4.0.3" source = "git+https://github.com/zed-industries/async-task?rev=341b57d6de98cdfd7b418567b8de2022ca993a6e#341b57d6de98cdfd7b418567b8de2022ca993a6e" +[[package]] +name = "atomic" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3410529e8288c463bedb5930f82833bc0c90e5d2fe639a56582a4d09220b281" +dependencies = [ + "autocfg", +] + [[package]] name = "atomic-waker" version = "1.0.0" @@ -524,6 +533,16 @@ dependencies = [ "crossbeam-utils 0.8.2", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f6cb3c7f5b8e51bc3ebb73a2327ad4abdbd119dc13223f14f961d2f38486756" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils 0.8.2", +] + [[package]] name = "crossbeam-utils" version = "0.7.2" @@ -799,6 +818,20 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +[[package]] +name = "futures" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9052a1a50244d8d5aa9bf55cbc2fb6f357c86cc52e46c62ed390a7180cf150" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.12" @@ -806,6 +839,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2d31b7ec7efab6eefc7c57233bb10b847986139d88cc2f5a02a1ae6871a1846" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -835,6 +869,31 @@ dependencies = [ "waker-fn", ] +[[package]] +name = "futures-sink" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5629433c555de3d82861a7a4e3794a4c40040390907cfbfd7143a92a426c23" + +[[package]] +name = "futures-task" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba7aa51095076f3ba6d9a1f702f74bd05ec65f555d70d2033d55ba8d69f581bc" + +[[package]] +name = "futures-util" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "632a8cd0f2a4b3fdea1657f08bde063848c3bd00f9bbf6e256b8be78802e624b" +dependencies = [ + "futures-core", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", +] + [[package]] name = "generator" version = "0.6.23" @@ -1328,6 +1387,26 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d70072c20945e1ab871c472a285fc772aefd4f5407723c206242f2c6f94595d6" +[[package]] +name = "pin-project" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc174859768806e91ae575187ada95c91a29e96a98dc5d2cd9a1fed039501ba6" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a490329918e856ed1b083f244e3bfe2d8c4f336407e4ea9e1a9f479ff09049e5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pin-project-lite" version = "0.2.4" @@ -1371,6 +1450,28 @@ dependencies = [ "winapi", ] +[[package]] +name = "pollster" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cce106fd2646acbe31a0e4006f75779d535c26a44f153ada196e9edcfc6d944" + +[[package]] +name = "postage" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a63d25391d04a097954b76aba742b6b5b74f213dfe3dbaeeb36e8ddc1c657f0b" +dependencies = [ + "atomic", + "crossbeam-queue", + "futures", + "log", + "pin-project", + "pollster", + "static_assertions", + "thiserror", +] + [[package]] name = "ppv-lite86" version = "0.2.10" @@ -1862,6 +1963,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.8.0" @@ -1933,6 +2040,26 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thiserror" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.3" @@ -2298,6 +2425,7 @@ dependencies = [ "log", "num_cpus", "parking_lot", + "postage", "rand 0.8.3", "rust-embed", "seahash", diff --git a/zed/Cargo.toml b/zed/Cargo.toml index 4ed0d1f1d5..1f6cec6e9b 100644 --- a/zed/Cargo.toml +++ b/zed/Cargo.toml @@ -26,6 +26,7 @@ libc = "0.2" log = "0.4" num_cpus = "1.13.0" parking_lot = "0.11.1" +postage = {version = "0.4.1", features = ["futures-traits"]} rand = "0.8.3" rust-embed = "5.9.0" seahash = "4.1" diff --git a/zed/src/lib.rs b/zed/src/lib.rs index 14c2369258..066f07a20f 100644 --- a/zed/src/lib.rs +++ b/zed/src/lib.rs @@ -7,6 +7,7 @@ pub mod settings; mod sum_tree; #[cfg(test)] mod test; +mod throttle; mod time; mod timer; mod util; diff --git a/zed/src/worktree/worktree.rs b/zed/src/worktree/worktree.rs index e7f1714427..7d1d769593 100644 --- a/zed/src/worktree/worktree.rs +++ b/zed/src/worktree/worktree.rs @@ -5,7 +5,7 @@ use super::{ }; use crate::{ editor::{History, Snapshot}, - timer, + throttle::throttled, util::post_inc, }; use anyhow::{anyhow, Result}; @@ -14,6 +14,7 @@ use easy_parallel::Parallel; use gpui::{scoped_pool, AppContext, Entity, ModelContext, ModelHandle, Task}; use ignore::dir::{Ignore, IgnoreBuilder}; use parking_lot::RwLock; +use postage::watch; use smol::prelude::*; use std::{ collections::HashMap, @@ -37,7 +38,13 @@ struct WorktreeState { entries: HashMap, file_paths: Vec, histories: HashMap, - scanning: bool, + scan_state: watch::Sender, +} + +#[derive(Clone)] +enum ScanState { + Scanning, + Idle, } struct DirToScan { @@ -53,6 +60,8 @@ impl Worktree { where T: Into, { + let scan_state = watch::channel_with(ScanState::Scanning); + let tree = Self(Arc::new(RwLock::new(WorktreeState { id, path: path.into(), @@ -60,22 +69,22 @@ impl Worktree { entries: HashMap::new(), file_paths: Vec::new(), histories: HashMap::new(), - scanning: true, + scan_state: scan_state.0, }))); - let done_scanning = { + { let tree = tree.clone(); - ctx.background_executor().spawn(async move { - tree.scan_dirs()?; - Ok(()) - }) - }; - - ctx.spawn(done_scanning, Self::done_scanning).detach(); + std::thread::spawn(move || { + if let Err(error) = tree.scan_dirs() { + log::error!("error scanning worktree: {}", error); + } + tree.set_scan_state(ScanState::Idle); + }); + } ctx.spawn_stream( - timer::repeat(Duration::from_millis(100)).map(|_| ()), - Self::scanning, + throttled(Duration::from_millis(100), scan_state.1), + Self::observe_scan_state, |_, _| {}, ) .detach(); @@ -83,6 +92,10 @@ impl Worktree { tree } + fn set_scan_state(&self, state: ScanState) { + *self.0.write().scan_state.borrow_mut() = state; + } + fn scan_dirs(&self) -> io::Result<()> { let path = self.0.read().path.clone(); let metadata = fs::metadata(&path)?; @@ -201,7 +214,8 @@ impl Worktree { is_symlink: bool, is_ignored: bool, ) { - let entries = &mut self.0.write().entries; + let mut state = self.0.write(); + let entries = &mut state.entries; entries.insert( ino, Entry::Dir { @@ -213,6 +227,7 @@ impl Worktree { children: Vec::new(), }, ); + *state.scan_state.borrow_mut() = ScanState::Scanning; } fn insert_file( @@ -247,6 +262,7 @@ impl Worktree { lowercase_path, is_ignored, }); + *state.scan_state.borrow_mut() = ScanState::Scanning; } pub fn entry_path(&self, mut entry_id: u64) -> Result { @@ -394,22 +410,9 @@ impl Worktree { }) } - fn scanning(&mut self, _: (), ctx: &mut ModelContext) { - if self.0.read().scanning { - ctx.notify(); - } else { - ctx.halt_stream(); - } - } - - fn done_scanning(&mut self, result: io::Result<()>, ctx: &mut ModelContext) { - log::info!("done scanning"); - self.0.write().scanning = false; - if let Err(error) = result { - log::error!("error populating worktree: {}", error); - } else { - ctx.notify(); - } + fn observe_scan_state(&mut self, _: ScanState, ctx: &mut ModelContext) { + // log::info!("observe {:?}", std::time::Instant::now()); + ctx.notify() } }