@@ -14,101 +14,39 @@ use std::sync::Arc;
1414use std:: sync:: LazyLock ;
1515use std:: sync:: OnceLock ;
1616
17- use arc_swap :: ArcSwap ;
18- use parking_lot :: Mutex ;
17+ use lasso :: Spur ;
18+ use lasso :: ThreadedRodeo ;
1919use parking_lot:: RwLock ;
20- use string_interner:: DefaultBackend ;
21- use string_interner:: DefaultSymbol ;
22- use string_interner:: StringInterner ;
2320use vortex_error:: VortexExpect ;
2421use vortex_utils:: aliases:: dash_map:: DashMap ;
2522
2623/// Global string interner for [`Id`] values.
27- static INTERNER : LazyLock < Interner > = LazyLock :: new ( Interner :: default) ;
28-
29- struct Interner {
30- state : ArcSwap < StringInterner < DefaultBackend > > ,
31- write_lock : Mutex < ( ) > ,
32- }
33-
34- impl Default for Interner {
35- fn default ( ) -> Self {
36- Self {
37- state : ArcSwap :: from_pointee ( StringInterner :: with_capacity ( 200 ) ) ,
38- write_lock : Mutex :: new ( ( ) ) ,
39- }
40- }
41- }
42-
43- impl Interner {
44- fn intern_static ( & self , s : & ' static str ) -> DefaultSymbol {
45- if let Some ( symbol) = self . state . load ( ) . get ( s) {
46- return symbol;
47- }
48-
49- // Ensure if we need to add this we have the write lock and check again if its was
50- // added just now.
51- let _guard = self . write_lock . lock ( ) ;
52- let state = self . state . load_full ( ) ;
53- if let Some ( symbol) = state. get ( s) {
54- return symbol;
55- }
56-
57- let mut next = ( * state) . clone ( ) ;
58- let symbol = next. get_or_intern_static ( s) ;
59- self . state . store ( Arc :: new ( next) ) ;
60- symbol
61- }
62-
63- fn intern ( & self , s : & str ) -> DefaultSymbol {
64- if let Some ( symbol) = self . state . load ( ) . get ( s) {
65- return symbol;
66- }
67-
68- // Ensure if we need to add this we have the write lock and check again if its was
69- // added just now.
70- let _guard = self . write_lock . lock ( ) ;
71- let state = self . state . load_full ( ) ;
72- if let Some ( symbol) = state. get ( s) {
73- return symbol;
74- }
75-
76- let mut next = ( * state) . clone ( ) ;
77- let symbol = next. get_or_intern ( s) ;
78- self . state . store ( Arc :: new ( next) ) ;
79- symbol
80- }
81- }
24+ static INTERNER : LazyLock < ThreadedRodeo > = LazyLock :: new ( ThreadedRodeo :: new) ;
8225
8326/// A lightweight, copyable identifier backed by a global string interner.
8427///
8528/// Used for array encoding IDs, scalar function IDs, layout IDs, and similar
8629/// globally-unique string identifiers throughout Vortex. Equality and hashing
8730/// are O(1) symbol comparisons.
8831#[ derive( Clone , Copy , PartialEq , Eq , Hash ) ]
89- pub struct Id ( DefaultSymbol ) ;
32+ pub struct Id ( Spur ) ;
9033
9134impl Id {
9235 /// Intern a string and return its `Id`.
9336 pub fn new ( s : & str ) -> Self {
94- Self ( INTERNER . intern ( s) )
37+ Self ( INTERNER . get_or_intern ( s) )
9538 }
9639
9740 /// Intern a string and return its `Id`.
9841 pub fn new_static ( s : & ' static str ) -> Self {
99- Self ( INTERNER . intern_static ( s) )
42+ Self ( INTERNER . get_or_intern_static ( s) )
10043 }
10144
10245 /// Returns the interned string.
10346 pub fn as_str ( & self ) -> & str {
104- // SAFETY: The interner is append-only (symbols are never removed), so the resolved
105- // string reference is valid for the lifetime of this borrow.
106- let interner = INTERNER . state . load ( ) ;
107- let s = interner
108- . resolve ( self . 0 )
109- . vortex_expect ( "Id symbol not found in interner" ) ;
110- // SAFETY: The interner is append-only and lives for 'static, so the &str is valid
111- // for the program's lifetime. We just can't express that through the RwLock borrow.
47+ let s = INTERNER . resolve ( & self . 0 ) ;
48+ // SAFETY: INTERNER is 'static and its arena is append-only, so resolved string
49+ // pointers are stable for the lifetime of the program.
11250 unsafe { & * ( s as * const str ) }
11351 }
11452}
0 commit comments