@@ -777,6 +777,48 @@ impl AstIdMap {
777777 }
778778}
779779
780+ #[ cfg( not( no_salsa_async_drops) ) ]
781+ impl Drop for AstIdMap {
782+ fn drop ( & mut self ) {
783+ let arena = std:: mem:: take ( & mut self . arena ) ;
784+ let ptr_map = std:: mem:: take ( & mut self . ptr_map ) ;
785+ let id_map = std:: mem:: take ( & mut self . id_map ) ;
786+ static AST_ID_MAP_DROP_THREAD : std:: sync:: OnceLock <
787+ std:: sync:: mpsc:: Sender < (
788+ Arena < ( SyntaxNodePtr , ErasedFileAstId ) > ,
789+ hashbrown:: HashTable < ArenaId > ,
790+ hashbrown:: HashTable < ArenaId > ,
791+ ) > ,
792+ > = std:: sync:: OnceLock :: new ( ) ;
793+ AST_ID_MAP_DROP_THREAD
794+ . get_or_init ( || {
795+ let ( sender, receiver) = std:: sync:: mpsc:: channel :: < (
796+ Arena < ( SyntaxNodePtr , ErasedFileAstId ) > ,
797+ hashbrown:: HashTable < ArenaId > ,
798+ hashbrown:: HashTable < ArenaId > ,
799+ ) > ( ) ;
800+ std:: thread:: Builder :: new ( )
801+ . name ( "AstIdMapDropper" . to_owned ( ) )
802+ . spawn ( move || {
803+ loop {
804+ // block on a receive
805+ _ = receiver. recv ( ) ;
806+ // then drain the entire channel
807+ while let Ok ( _) = receiver. try_recv ( ) { }
808+ // and sleep for a bit
809+ std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 100 ) ) ;
810+ }
811+ // why do this over just a `receiver.iter().for_each(drop)`? To reduce contention on the channel lock.
812+ // otherwise this thread will constantly wake up and sleep again.
813+ } )
814+ . unwrap ( ) ;
815+ sender
816+ } )
817+ . send ( ( arena, ptr_map, id_map) )
818+ . unwrap ( ) ;
819+ }
820+ }
821+
780822#[ inline]
781823fn hash_ptr ( ptr : & SyntaxNodePtr ) -> u64 {
782824 FxBuildHasher . hash_one ( ptr)
0 commit comments