Avoid retaining executor in the FakeFs
This probably isn't the *root* cause of why an executor is leaked, but by cutting off this cyclic references, it may make it a bit easier to track down leaks of an executor.
This commit is contained in:
parent
3788efeadf
commit
1faaa91e52
1 changed files with 20 additions and 12 deletions
|
@ -267,13 +267,13 @@ impl FakeFsState {
|
||||||
pub struct FakeFs {
|
pub struct FakeFs {
|
||||||
// Use an unfair lock to ensure tests are deterministic.
|
// Use an unfair lock to ensure tests are deterministic.
|
||||||
state: futures::lock::Mutex<FakeFsState>,
|
state: futures::lock::Mutex<FakeFsState>,
|
||||||
executor: std::sync::Arc<gpui::executor::Background>,
|
executor: std::sync::Weak<gpui::executor::Background>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
impl FakeFs {
|
impl FakeFs {
|
||||||
pub fn new(executor: std::sync::Arc<gpui::executor::Background>) -> std::sync::Arc<Self> {
|
pub fn new(executor: std::sync::Arc<gpui::executor::Background>) -> std::sync::Arc<Self> {
|
||||||
let (events_tx, _) = postage::broadcast::channel(2048);
|
let (events_tx, _) = postage::broadcast::channel(2);
|
||||||
let mut entries = std::collections::BTreeMap::new();
|
let mut entries = std::collections::BTreeMap::new();
|
||||||
entries.insert(
|
entries.insert(
|
||||||
Path::new("/").to_path_buf(),
|
Path::new("/").to_path_buf(),
|
||||||
|
@ -288,7 +288,7 @@ impl FakeFs {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
std::sync::Arc::new(Self {
|
std::sync::Arc::new(Self {
|
||||||
executor,
|
executor: std::sync::Arc::downgrade(&executor),
|
||||||
state: futures::lock::Mutex::new(FakeFsState {
|
state: futures::lock::Mutex::new(FakeFsState {
|
||||||
entries,
|
entries,
|
||||||
next_inode: 1,
|
next_inode: 1,
|
||||||
|
@ -375,13 +375,21 @@ impl FakeFs {
|
||||||
}
|
}
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn simulate_random_delay(&self) {
|
||||||
|
self.executor
|
||||||
|
.upgrade()
|
||||||
|
.expect("excecutor has been dropped")
|
||||||
|
.simulate_random_delay()
|
||||||
|
.await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl Fs for FakeFs {
|
impl Fs for FakeFs {
|
||||||
async fn create_dir(&self, path: &Path) -> Result<()> {
|
async fn create_dir(&self, path: &Path) -> Result<()> {
|
||||||
self.executor.simulate_random_delay().await;
|
self.simulate_random_delay().await;
|
||||||
let state = &mut *self.state.lock().await;
|
let state = &mut *self.state.lock().await;
|
||||||
let path = normalize_path(path);
|
let path = normalize_path(path);
|
||||||
let mut ancestor_path = PathBuf::new();
|
let mut ancestor_path = PathBuf::new();
|
||||||
|
@ -418,7 +426,7 @@ impl Fs for FakeFs {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_file(&self, path: &Path, options: CreateOptions) -> Result<()> {
|
async fn create_file(&self, path: &Path, options: CreateOptions) -> Result<()> {
|
||||||
self.executor.simulate_random_delay().await;
|
self.simulate_random_delay().await;
|
||||||
let mut state = self.state.lock().await;
|
let mut state = self.state.lock().await;
|
||||||
let path = normalize_path(path);
|
let path = normalize_path(path);
|
||||||
state.validate_path(&path)?;
|
state.validate_path(&path)?;
|
||||||
|
@ -546,7 +554,7 @@ impl Fs for FakeFs {
|
||||||
|
|
||||||
async fn load(&self, path: &Path) -> Result<String> {
|
async fn load(&self, path: &Path) -> Result<String> {
|
||||||
let path = normalize_path(path);
|
let path = normalize_path(path);
|
||||||
self.executor.simulate_random_delay().await;
|
self.simulate_random_delay().await;
|
||||||
let state = self.state.lock().await;
|
let state = self.state.lock().await;
|
||||||
let text = state
|
let text = state
|
||||||
.entries
|
.entries
|
||||||
|
@ -557,7 +565,7 @@ impl Fs for FakeFs {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save(&self, path: &Path, text: &Rope) -> Result<()> {
|
async fn save(&self, path: &Path, text: &Rope) -> Result<()> {
|
||||||
self.executor.simulate_random_delay().await;
|
self.simulate_random_delay().await;
|
||||||
let mut state = self.state.lock().await;
|
let mut state = self.state.lock().await;
|
||||||
let path = normalize_path(path);
|
let path = normalize_path(path);
|
||||||
state.validate_path(&path)?;
|
state.validate_path(&path)?;
|
||||||
|
@ -589,13 +597,13 @@ impl Fs for FakeFs {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn canonicalize(&self, path: &Path) -> Result<PathBuf> {
|
async fn canonicalize(&self, path: &Path) -> Result<PathBuf> {
|
||||||
self.executor.simulate_random_delay().await;
|
self.simulate_random_delay().await;
|
||||||
Ok(normalize_path(path))
|
Ok(normalize_path(path))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn is_file(&self, path: &Path) -> bool {
|
async fn is_file(&self, path: &Path) -> bool {
|
||||||
let path = normalize_path(path);
|
let path = normalize_path(path);
|
||||||
self.executor.simulate_random_delay().await;
|
self.simulate_random_delay().await;
|
||||||
let state = self.state.lock().await;
|
let state = self.state.lock().await;
|
||||||
state
|
state
|
||||||
.entries
|
.entries
|
||||||
|
@ -604,7 +612,7 @@ impl Fs for FakeFs {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn metadata(&self, path: &Path) -> Result<Option<Metadata>> {
|
async fn metadata(&self, path: &Path) -> Result<Option<Metadata>> {
|
||||||
self.executor.simulate_random_delay().await;
|
self.simulate_random_delay().await;
|
||||||
let state = self.state.lock().await;
|
let state = self.state.lock().await;
|
||||||
let path = normalize_path(path);
|
let path = normalize_path(path);
|
||||||
Ok(state.entries.get(&path).map(|entry| entry.metadata.clone()))
|
Ok(state.entries.get(&path).map(|entry| entry.metadata.clone()))
|
||||||
|
@ -615,7 +623,7 @@ impl Fs for FakeFs {
|
||||||
abs_path: &Path,
|
abs_path: &Path,
|
||||||
) -> Result<Pin<Box<dyn Send + Stream<Item = Result<PathBuf>>>>> {
|
) -> Result<Pin<Box<dyn Send + Stream<Item = Result<PathBuf>>>>> {
|
||||||
use futures::{future, stream};
|
use futures::{future, stream};
|
||||||
self.executor.simulate_random_delay().await;
|
self.simulate_random_delay().await;
|
||||||
let state = self.state.lock().await;
|
let state = self.state.lock().await;
|
||||||
let abs_path = normalize_path(abs_path);
|
let abs_path = normalize_path(abs_path);
|
||||||
Ok(Box::pin(stream::iter(state.entries.clone()).filter_map(
|
Ok(Box::pin(stream::iter(state.entries.clone()).filter_map(
|
||||||
|
@ -635,7 +643,7 @@ impl Fs for FakeFs {
|
||||||
_: Duration,
|
_: Duration,
|
||||||
) -> Pin<Box<dyn Send + Stream<Item = Vec<fsevent::Event>>>> {
|
) -> Pin<Box<dyn Send + Stream<Item = Vec<fsevent::Event>>>> {
|
||||||
let state = self.state.lock().await;
|
let state = self.state.lock().await;
|
||||||
self.executor.simulate_random_delay().await;
|
self.simulate_random_delay().await;
|
||||||
let rx = state.events_tx.subscribe();
|
let rx = state.events_tx.subscribe();
|
||||||
let path = path.to_path_buf();
|
let path = path.to_path_buf();
|
||||||
Box::pin(futures::StreamExt::filter(rx, move |events| {
|
Box::pin(futures::StreamExt::filter(rx, move |events| {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue