@@ -5,6 +5,7 @@ use std::{
5
5
ptr:: { self , NonNull } ,
6
6
} ;
7
7
8
+ use portable_atomic:: hint:: spin_loop;
8
9
use thin_vec:: ThinVec ;
9
10
10
11
use crate :: sync:: atomic:: { AtomicPtr , Ordering } ;
@@ -47,6 +48,7 @@ struct MemoEntry {
47
48
atomic_memo : AtomicPtr < DummyMemo > ,
48
49
}
49
50
51
+ #[ derive( Default ) ]
50
52
pub struct MemoEntryType {
51
53
data : OnceLock < MemoEntryTypeData > ,
52
54
}
@@ -120,22 +122,34 @@ impl MemoTableTypes {
120
122
memo_type : & MemoEntryType ,
121
123
) {
122
124
let memo_ingredient_index = memo_ingredient_index. as_usize ( ) ;
123
- while memo_ingredient_index >= self . types . count ( ) {
124
- self . types . push ( MemoEntryType {
125
- data : OnceLock :: new ( ) ,
126
- } ) ;
125
+
126
+ // Try to create our entry if it has not already been created.
127
+ if memo_ingredient_index >= self . types . count ( ) {
128
+ while self . types . push ( MemoEntryType :: default ( ) ) < memo_ingredient_index { }
129
+ }
130
+
131
+ loop {
132
+ let Some ( memo_entry_type) = self . types . get ( memo_ingredient_index) else {
133
+ // It's possible that someone else began pushing to our index but has not
134
+ // completed the entry's initialization yet, as `boxcar` is lock-free. This
135
+ // is extremely unlikely given initialization is just a handful of instructions.
136
+ // Additionally, this function is generally only called on startup, so we can
137
+ // just spin here.
138
+ spin_loop ( ) ;
139
+ continue ;
140
+ } ;
141
+
142
+ memo_entry_type
143
+ . data
144
+ . set (
145
+ * memo_type. data . get ( ) . expect (
146
+ "cannot provide an empty `MemoEntryType` for `MemoEntryType::set()`" ,
147
+ ) ,
148
+ )
149
+ . ok ( )
150
+ . expect ( "memo type should only be set once" ) ;
151
+ break ;
127
152
}
128
- let memo_entry_type = self . types . get ( memo_ingredient_index) . unwrap ( ) ;
129
- memo_entry_type
130
- . data
131
- . set (
132
- * memo_type
133
- . data
134
- . get ( )
135
- . expect ( "cannot provide an empty `MemoEntryType` for `MemoEntryType::set()`" ) ,
136
- )
137
- . ok ( )
138
- . expect ( "memo type should only be set once" ) ;
139
153
}
140
154
141
155
/// # Safety
0 commit comments