Shuffle some locking around
This commit is contained in:
parent
70e21dc30b
commit
cc8b78601d
@ -12,12 +12,12 @@
|
|||||||
use load_cargo::SourceRootConfig;
|
use load_cargo::SourceRootConfig;
|
||||||
use lsp_types::{SemanticTokens, Url};
|
use lsp_types::{SemanticTokens, Url};
|
||||||
use nohash_hasher::IntMap;
|
use nohash_hasher::IntMap;
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard};
|
||||||
use proc_macro_api::ProcMacroServer;
|
use proc_macro_api::ProcMacroServer;
|
||||||
use project_model::{CargoWorkspace, ProjectWorkspace, Target, WorkspaceBuildScripts};
|
use project_model::{CargoWorkspace, ProjectWorkspace, Target, WorkspaceBuildScripts};
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
use vfs::AnchoredPathBuf;
|
use vfs::{AnchoredPathBuf, Vfs};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{Config, ConfigError},
|
config::{Config, ConfigError},
|
||||||
@ -216,12 +216,15 @@ pub(crate) fn process_changes(&mut self) -> bool {
|
|||||||
let mut file_changes = FxHashMap::default();
|
let mut file_changes = FxHashMap::default();
|
||||||
let (change, changed_files, workspace_structure_change) = {
|
let (change, changed_files, workspace_structure_change) = {
|
||||||
let mut change = Change::new();
|
let mut change = Change::new();
|
||||||
let (vfs, line_endings_map) = &mut *self.vfs.write();
|
let mut guard = self.vfs.write();
|
||||||
let changed_files = vfs.take_changes();
|
let changed_files = guard.0.take_changes();
|
||||||
if changed_files.is_empty() {
|
if changed_files.is_empty() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// downgrade to read lock to allow more readers while we are normalizing text
|
||||||
|
let guard = RwLockWriteGuard::downgrade_to_upgradable(guard);
|
||||||
|
let vfs: &Vfs = &guard.0;
|
||||||
// We need to fix up the changed events a bit. If we have a create or modify for a file
|
// We need to fix up the changed events a bit. If we have a create or modify for a file
|
||||||
// id that is followed by a delete we actually skip observing the file text from the
|
// id that is followed by a delete we actually skip observing the file text from the
|
||||||
// earlier event, to avoid problems later on.
|
// earlier event, to avoid problems later on.
|
||||||
@ -272,6 +275,7 @@ pub(crate) fn process_changes(&mut self) -> bool {
|
|||||||
let mut workspace_structure_change = None;
|
let mut workspace_structure_change = None;
|
||||||
// A file was added or deleted
|
// A file was added or deleted
|
||||||
let mut has_structure_changes = false;
|
let mut has_structure_changes = false;
|
||||||
|
let mut bytes = vec![];
|
||||||
for file in &changed_files {
|
for file in &changed_files {
|
||||||
let vfs_path = &vfs.file_path(file.file_id);
|
let vfs_path = &vfs.file_path(file.file_id);
|
||||||
if let Some(path) = vfs_path.as_path() {
|
if let Some(path) = vfs_path.as_path() {
|
||||||
@ -293,16 +297,28 @@ pub(crate) fn process_changes(&mut self) -> bool {
|
|||||||
|
|
||||||
let text = if file.exists() {
|
let text = if file.exists() {
|
||||||
let bytes = vfs.file_contents(file.file_id).to_vec();
|
let bytes = vfs.file_contents(file.file_id).to_vec();
|
||||||
|
|
||||||
String::from_utf8(bytes).ok().and_then(|text| {
|
String::from_utf8(bytes).ok().and_then(|text| {
|
||||||
|
// FIXME: Consider doing normalization in the `vfs` instead? That allows
|
||||||
|
// getting rid of some locking
|
||||||
let (text, line_endings) = LineEndings::normalize(text);
|
let (text, line_endings) = LineEndings::normalize(text);
|
||||||
line_endings_map.insert(file.file_id, line_endings);
|
Some((Arc::from(text), line_endings))
|
||||||
Some(Arc::from(text))
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
change.change_file(file.file_id, text);
|
// delay `line_endings_map` changes until we are done normalizing the text
|
||||||
|
// this allows delaying the re-acquisition of the write lock
|
||||||
|
bytes.push((file.file_id, text));
|
||||||
}
|
}
|
||||||
|
let (vfs, line_endings_map) = &mut *RwLockUpgradableReadGuard::upgrade(guard);
|
||||||
|
bytes.into_iter().for_each(|(file_id, text)| match text {
|
||||||
|
None => change.change_file(file_id, None),
|
||||||
|
Some((text, line_endings)) => {
|
||||||
|
line_endings_map.insert(file_id, line_endings);
|
||||||
|
change.change_file(file_id, Some(text));
|
||||||
|
}
|
||||||
|
});
|
||||||
if has_structure_changes {
|
if has_structure_changes {
|
||||||
let roots = self.source_root_config.partition(vfs);
|
let roots = self.source_root_config.partition(vfs);
|
||||||
change.set_roots(roots);
|
change.set_roots(roots);
|
||||||
|
@ -84,15 +84,16 @@ pub(crate) fn handle_did_change_text_document(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let vfs = &mut state.vfs.write().0;
|
|
||||||
let file_id = vfs.file_id(&path).unwrap();
|
|
||||||
let text = apply_document_changes(
|
let text = apply_document_changes(
|
||||||
state.config.position_encoding(),
|
state.config.position_encoding(),
|
||||||
|| std::str::from_utf8(vfs.file_contents(file_id)).unwrap().into(),
|
|| {
|
||||||
|
let vfs = &state.vfs.read().0;
|
||||||
|
let file_id = vfs.file_id(&path).unwrap();
|
||||||
|
std::str::from_utf8(vfs.file_contents(file_id)).unwrap().into()
|
||||||
|
},
|
||||||
params.content_changes,
|
params.content_changes,
|
||||||
);
|
);
|
||||||
|
state.vfs.write().0.set_file_contents(path, Some(text.into_bytes()));
|
||||||
vfs.set_file_contents(path, Some(text.into_bytes()));
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user