Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/span/src/ast_id.rs')
-rw-r--r--crates/span/src/ast_id.rs47
1 files changed, 45 insertions, 2 deletions
diff --git a/crates/span/src/ast_id.rs b/crates/span/src/ast_id.rs
index e54e0bd2fc..599b3c7175 100644
--- a/crates/span/src/ast_id.rs
+++ b/crates/span/src/ast_id.rs
@@ -603,8 +603,9 @@ impl AstIdMap {
// After all, the block will then contain the *outer* item, so we allocate
// an ID for it anyway.
let mut blocks = Vec::new();
- let mut curr_layer = vec![(node.clone(), None)];
- let mut next_layer = vec![];
+ let mut curr_layer = Vec::with_capacity(32);
+ curr_layer.push((node.clone(), None));
+ let mut next_layer = Vec::with_capacity(32);
while !curr_layer.is_empty() {
curr_layer.drain(..).for_each(|(node, parent_idx)| {
let mut preorder = node.preorder();
@@ -776,6 +777,48 @@ impl AstIdMap {
}
}
+#[cfg(not(no_salsa_async_drops))]
+impl Drop for AstIdMap {
+ fn drop(&mut self) {
+ let arena = std::mem::take(&mut self.arena);
+ let ptr_map = std::mem::take(&mut self.ptr_map);
+ let id_map = std::mem::take(&mut self.id_map);
+ static AST_ID_MAP_DROP_THREAD: std::sync::OnceLock<
+ std::sync::mpsc::Sender<(
+ Arena<(SyntaxNodePtr, ErasedFileAstId)>,
+ hashbrown::HashTable<ArenaId>,
+ hashbrown::HashTable<ArenaId>,
+ )>,
+ > = std::sync::OnceLock::new();
+ AST_ID_MAP_DROP_THREAD
+ .get_or_init(|| {
+ let (sender, receiver) = std::sync::mpsc::channel::<(
+ Arena<(SyntaxNodePtr, ErasedFileAstId)>,
+ hashbrown::HashTable<ArenaId>,
+ hashbrown::HashTable<ArenaId>,
+ )>();
+ std::thread::Builder::new()
+ .name("AstIdMapDropper".to_owned())
+ .spawn(move || {
+ loop {
+ // block on a receive
+ _ = receiver.recv();
+ // then drain the entire channel
+ while receiver.try_recv().is_ok() {}
+ // and sleep for a bit
+ std::thread::sleep(std::time::Duration::from_millis(100));
+ }
+ // why do this over just a `receiver.iter().for_each(drop)`? To reduce contention on the channel lock.
+ // otherwise this thread will constantly wake up and sleep again.
+ })
+ .unwrap();
+ sender
+ })
+ .send((arena, ptr_map, id_map))
+ .unwrap();
+ }
+}
+
#[inline]
fn hash_ptr(ptr: &SyntaxNodePtr) -> u64 {
FxBuildHasher.hash_one(ptr)