Rework Worktree::scan_complete to use a watch

This commit is contained in:
Antonio Scandurra 2021-04-20 11:24:46 +02:00
parent a4c1fe5a0b
commit d11d5483b6

View file

@ -6,20 +6,21 @@ use crate::{
sum_tree::{self, Edit, SumTree},
};
use anyhow::{anyhow, Result};
use futures_core::future::BoxFuture;
pub use fuzzy::match_paths;
use fuzzy::PathEntry;
pub use fuzzy::{match_paths, PathMatch};
use gpui::{scoped_pool, AppContext, Entity, ModelContext, ModelHandle, Task};
use ignore::dir::{Ignore, IgnoreBuilder};
use parking_lot::Mutex;
use postage::{oneshot, prelude::Stream, sink::Sink};
use postage::{
prelude::{Sink, Stream},
watch,
};
use smol::{channel::Sender, Timer};
use std::{
ffi::OsStr,
fmt, fs,
future::Future,
io::{self, Read, Write},
mem,
ops::{AddAssign, Deref},
os::unix::fs::MetadataExt,
path::{Path, PathBuf},
@ -27,20 +28,17 @@ use std::{
time::Duration,
};
pub use fuzzy::PathMatch;
#[derive(Debug)]
#[derive(Clone, Debug)]
enum ScanState {
Idle,
Scanning,
Err(io::Error),
Err(Arc<io::Error>),
}
pub struct Worktree {
snapshot: Snapshot,
scanner: Arc<BackgroundScanner>,
scan_listeners: Mutex<Vec<postage::oneshot::Sender<()>>>,
scan_state: ScanState,
scan_state: (watch::Sender<ScanState>, watch::Receiver<ScanState>),
poll_scheduled: bool,
}
@ -63,8 +61,7 @@ impl Worktree {
let tree = Self {
snapshot,
scanner,
scan_listeners: Default::default(),
scan_state: ScanState::Scanning,
scan_state: watch::channel_with(ScanState::Scanning),
poll_scheduled: false,
};
@ -77,20 +74,18 @@ impl Worktree {
tree
}
pub fn scan_complete(&self) -> BoxFuture<'static, ()> {
if self.is_scanning() {
let (tx, mut rx) = oneshot::channel::<()>();
self.scan_listeners.lock().push(tx);
Box::pin(async move {
rx.recv().await;
})
} else {
Box::pin(async {})
pub fn scan_complete(&self) -> impl Future<Output = ()> {
let mut scan_state_rx = self.scan_state.1.clone();
async move {
let mut next_scan_state = Some(scan_state_rx.borrow().clone());
while let Some(ScanState::Scanning) = next_scan_state {
next_scan_state = scan_state_rx.recv().await;
}
}
}
fn observe_scan_state(&mut self, scan_state: ScanState, ctx: &mut ModelContext<Self>) {
self.scan_state = scan_state;
let _ = self.scan_state.0.blocking_send(scan_state);
self.poll_entries(ctx);
}
@ -105,23 +100,11 @@ impl Worktree {
})
.detach();
self.poll_scheduled = true;
} else {
let mut listeners = Vec::new();
mem::swap(self.scan_listeners.lock().as_mut(), &mut listeners);
ctx.spawn(
async move {
for mut tx in listeners {
tx.send(()).await.ok();
}
},
|_, _, _| {},
)
.detach();
}
}
fn is_scanning(&self) -> bool {
if let ScanState::Scanning = self.scan_state {
if let ScanState::Scanning = *self.scan_state.1.borrow() {
true
} else {
false
@ -554,7 +537,7 @@ impl BackgroundScanner {
}
if let Err(err) = self.scan_dirs() {
if smol::block_on(self.notify.send(ScanState::Err(err))).is_err() {
if smol::block_on(self.notify.send(ScanState::Err(Arc::new(err)))).is_err() {
return;
}
}