1
+ use super :: lazy:: LazyKeyInner ;
2
+ use crate :: cell:: Cell ;
3
+ use crate :: sys:: thread_local_dtor:: register_dtor;
4
+ use crate :: { fmt, mem, panic} ;
5
+
1
6
#[ doc( hidden) ]
2
- #[ macro_export]
3
- #[ allow_internal_unstable(
4
- thread_local_internals,
5
- cfg_target_thread_local,
6
- thread_local,
7
- libstd_thread_internals
8
- ) ]
7
+ #[ allow_internal_unstable( thread_local_internals, cfg_target_thread_local, thread_local) ]
9
8
#[ allow_internal_unsafe]
10
- macro_rules! __thread_local_inner {
9
+ #[ unstable( feature = "thread_local_internals" , issue = "none" ) ]
10
+ #[ rustc_macro_transparency = "semitransparent" ]
11
+ pub macro thread_local_inner {
11
12
// used to generate the `LocalKey` value for const-initialized thread locals
12
13
( @key $t: ty, const $init: expr) => { {
13
14
#[ cfg_attr( not( bootstrap) , inline) ]
@@ -49,7 +50,7 @@ macro_rules! __thread_local_inner {
49
50
// 0 == we haven't registered a destructor, so do
50
51
// so now.
51
52
0 => {
52
- $crate:: thread:: __LocalKeyInner :: <$t>:: register_dtor(
53
+ $crate:: thread:: local_impl :: Key :: < $t> :: register_dtor (
53
54
$crate:: ptr:: addr_of_mut!( VAL ) as * mut $crate:: primitive:: u8 ,
54
55
destroy,
55
56
) ;
@@ -69,7 +70,7 @@ macro_rules! __thread_local_inner {
69
70
unsafe {
70
71
$crate:: thread:: LocalKey :: new ( __getit)
71
72
}
72
- } } ;
73
+ } } ,
73
74
74
75
// used to generate the `LocalKey` value for `thread_local!`
75
76
( @key $t: ty, $init: expr) => {
@@ -82,8 +83,8 @@ macro_rules! __thread_local_inner {
82
83
init : $crate:: option:: Option < & mut $crate:: option:: Option < $t> > ,
83
84
) -> $crate:: option:: Option < & ' static $t> {
84
85
#[ thread_local]
85
- static __KEY: $crate:: thread:: __LocalKeyInner <$t> =
86
- $crate:: thread:: __LocalKeyInner :: <$t>:: new( ) ;
86
+ static __KEY: $crate:: thread:: local_impl :: Key < $t> =
87
+ $crate:: thread:: local_impl :: Key :: < $t> :: new ( ) ;
87
88
88
89
// FIXME: remove the #[allow(...)] marker when macros don't
89
90
// raise warning for missing/extraneous unsafe blocks anymore.
@@ -107,148 +108,140 @@ macro_rules! __thread_local_inner {
107
108
$crate:: thread:: LocalKey :: new ( __getit)
108
109
}
109
110
}
110
- } ;
111
+ } ,
111
112
( $( #[ $attr: meta] ) * $vis: vis $name: ident, $t: ty, $( $init: tt) * ) => {
112
113
$( #[ $attr] ) * $vis const $name: $crate:: thread:: LocalKey <$t> =
113
- $crate:: __thread_local_inner !( @key $t, $( $init) * ) ;
114
- }
114
+ $crate:: thread :: local_impl :: thread_local_inner !( @key $t, $( $init) * ) ;
115
+ } ,
115
116
}
116
117
117
- #[ doc( hidden) ]
118
- pub mod fast {
119
- use super :: super :: lazy:: LazyKeyInner ;
120
- use crate :: cell:: Cell ;
121
- use crate :: sys:: thread_local_dtor:: register_dtor;
122
- use crate :: { fmt, mem, panic} ;
123
-
124
- #[ derive( Copy , Clone ) ]
125
- enum DtorState {
126
- Unregistered ,
127
- Registered ,
128
- RunningOrHasRun ,
129
- }
118
+ #[ derive ( Copy , Clone ) ]
119
+ enum DtorState {
120
+ Unregistered ,
121
+ Registered ,
122
+ RunningOrHasRun ,
123
+ }
130
124
131
- // This data structure has been carefully constructed so that the fast path
132
- // only contains one branch on x86. That optimization is necessary to avoid
133
- // duplicated tls lookups on OSX.
125
+ // This data structure has been carefully constructed so that the fast path
126
+ // only contains one branch on x86. That optimization is necessary to avoid
127
+ // duplicated tls lookups on OSX.
128
+ //
129
+ // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
130
+ pub struct Key <T > {
131
+ // If `LazyKeyInner::get` returns `None`, that indicates either:
132
+ // * The value has never been initialized
133
+ // * The value is being recursively initialized
134
+ // * The value has already been destroyed or is being destroyed
135
+ // To determine which kind of `None`, check `dtor_state`.
134
136
//
135
- // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
136
- pub struct Key < T > {
137
- // If `LazyKeyInner::get` returns `None`, that indicates either:
138
- // * The value has never been initialized
139
- // * The value is being recursively initialized
140
- // * The value has already been destroyed or is being destroyed
141
- // To determine which kind of `None`, check `dtor_state`.
142
- //
143
- // This is very optimizer friendly for the fast path - initialized but
144
- // not yet dropped.
145
- inner : LazyKeyInner < T > ,
137
+ // This is very optimizer friendly for the fast path - initialized but
138
+ // not yet dropped.
139
+ inner: LazyKeyInner <T >,
146
140
147
- // Metadata to keep track of the state of the destructor. Remember that
148
- // this variable is thread-local, not global.
149
- dtor_state : Cell < DtorState > ,
150
- }
141
+ // Metadata to keep track of the state of the destructor. Remember that
142
+ // this variable is thread-local, not global.
143
+ dtor_state: Cell <DtorState >,
144
+ }
151
145
152
- impl < T > fmt:: Debug for Key < T > {
153
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
154
- f. debug_struct ( "Key" ) . finish_non_exhaustive ( )
155
- }
146
+ impl<T > fmt:: Debug for Key <T > {
147
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
148
+ f. debug_struct ( "Key" ) . finish_non_exhaustive ( )
156
149
}
150
+ }
157
151
158
- impl < T > Key < T > {
159
- pub const fn new ( ) -> Key < T > {
160
- Key { inner : LazyKeyInner :: new ( ) , dtor_state : Cell :: new ( DtorState :: Unregistered ) }
161
- }
152
+ impl < T > Key < T > {
153
+ pub const fn new ( ) -> Key < T > {
154
+ Key { inner : LazyKeyInner :: new ( ) , dtor_state : Cell :: new ( DtorState :: Unregistered ) }
155
+ }
162
156
163
- // note that this is just a publicly-callable function only for the
164
- // const-initialized form of thread locals, basically a way to call the
165
- // free `register_dtor` function defined elsewhere in std.
166
- pub unsafe fn register_dtor ( a : * mut u8 , dtor : unsafe extern "C" fn ( * mut u8 ) ) {
167
- unsafe {
168
- register_dtor ( a, dtor) ;
169
- }
157
+ // note that this is just a publicly-callable function only for the
158
+ // const-initialized form of thread locals, basically a way to call the
159
+ // free `register_dtor` function defined elsewhere in std.
160
+ pub unsafe fn register_dtor ( a : * mut u8 , dtor : unsafe extern "C" fn ( * mut u8 ) ) {
161
+ unsafe {
162
+ register_dtor ( a, dtor) ;
170
163
}
164
+ }
171
165
172
- pub unsafe fn get < F : FnOnce ( ) -> T > ( & self , init : F ) -> Option < & ' static T > {
173
- // SAFETY: See the definitions of `LazyKeyInner::get` and
174
- // `try_initialize` for more information.
175
- //
176
- // The caller must ensure no mutable references are ever active to
177
- // the inner cell or the inner T when this is called.
178
- // The `try_initialize` is dependant on the passed `init` function
179
- // for this.
180
- unsafe {
181
- match self . inner . get ( ) {
182
- Some ( val) => Some ( val) ,
183
- None => self . try_initialize ( init) ,
184
- }
166
+ pub unsafe fn get < F : FnOnce ( ) -> T > ( & self , init : F ) -> Option < & ' static T > {
167
+ // SAFETY: See the definitions of `LazyKeyInner::get` and
168
+ // `try_initialize` for more information.
169
+ //
170
+ // The caller must ensure no mutable references are ever active to
171
+ // the inner cell or the inner T when this is called.
172
+ // The `try_initialize` is dependant on the passed `init` function
173
+ // for this.
174
+ unsafe {
175
+ match self . inner . get ( ) {
176
+ Some ( val) => Some ( val) ,
177
+ None => self . try_initialize ( init) ,
185
178
}
186
179
}
180
+ }
187
181
188
- // `try_initialize` is only called once per fast thread local variable,
189
- // except in corner cases where thread_local dtors reference other
190
- // thread_local's, or it is being recursively initialized.
191
- //
192
- // Macos: Inlining this function can cause two `tlv_get_addr` calls to
193
- // be performed for every call to `Key::get`.
194
- // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
195
- #[ inline( never) ]
196
- unsafe fn try_initialize < F : FnOnce ( ) -> T > ( & self , init : F ) -> Option < & ' static T > {
182
+ // `try_initialize` is only called once per fast thread local variable,
183
+ // except in corner cases where thread_local dtors reference other
184
+ // thread_local's, or it is being recursively initialized.
185
+ //
186
+ // Macos: Inlining this function can cause two `tlv_get_addr` calls to
187
+ // be performed for every call to `Key::get`.
188
+ // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
189
+ #[ inline( never) ]
190
+ unsafe fn try_initialize < F : FnOnce ( ) -> T > ( & self , init : F ) -> Option < & ' static T > {
191
+ // SAFETY: See comment above (this function doc).
192
+ if !mem:: needs_drop :: < T > ( ) || unsafe { self . try_register_dtor ( ) } {
197
193
// SAFETY: See comment above (this function doc).
198
- if !mem:: needs_drop :: < T > ( ) || unsafe { self . try_register_dtor ( ) } {
199
- // SAFETY: See comment above (this function doc).
200
- Some ( unsafe { self . inner . initialize ( init) } )
201
- } else {
202
- None
203
- }
194
+ Some ( unsafe { self . inner . initialize ( init) } )
195
+ } else {
196
+ None
204
197
}
198
+ }
205
199
206
- // `try_register_dtor` is only called once per fast thread local
207
- // variable, except in corner cases where thread_local dtors reference
208
- // other thread_local's, or it is being recursively initialized.
209
- unsafe fn try_register_dtor ( & self ) -> bool {
210
- match self . dtor_state . get ( ) {
211
- DtorState :: Unregistered => {
212
- // SAFETY: dtor registration happens before initialization.
213
- // Passing `self` as a pointer while using `destroy_value<T>`
214
- // is safe because the function will build a pointer to a
215
- // Key<T>, which is the type of self and so find the correct
216
- // size.
217
- unsafe { register_dtor ( self as * const _ as * mut u8 , destroy_value :: < T > ) } ;
218
- self . dtor_state . set ( DtorState :: Registered ) ;
219
- true
220
- }
221
- DtorState :: Registered => {
222
- // recursively initialized
223
- true
224
- }
225
- DtorState :: RunningOrHasRun => false ,
200
+ // `try_register_dtor` is only called once per fast thread local
201
+ // variable, except in corner cases where thread_local dtors reference
202
+ // other thread_local's, or it is being recursively initialized.
203
+ unsafe fn try_register_dtor ( & self ) -> bool {
204
+ match self . dtor_state . get ( ) {
205
+ DtorState :: Unregistered => {
206
+ // SAFETY: dtor registration happens before initialization.
207
+ // Passing `self` as a pointer while using `destroy_value<T>`
208
+ // is safe because the function will build a pointer to a
209
+ // Key<T>, which is the type of self and so find the correct
210
+ // size.
211
+ unsafe { register_dtor ( self as * const _ as * mut u8 , destroy_value :: < T > ) } ;
212
+ self . dtor_state . set ( DtorState :: Registered ) ;
213
+ true
226
214
}
215
+ DtorState :: Registered => {
216
+ // recursively initialized
217
+ true
218
+ }
219
+ DtorState :: RunningOrHasRun => false ,
227
220
}
228
221
}
222
+ }
229
223
230
- unsafe extern "C" fn destroy_value < T > ( ptr : * mut u8 ) {
231
- let ptr = ptr as * mut Key < T > ;
224
+ unsafe extern "C" fn destroy_value < T > ( ptr : * mut u8 ) {
225
+ let ptr = ptr as * mut Key < T > ;
232
226
233
- // SAFETY:
234
- //
235
- // The pointer `ptr` has been built just above and comes from
236
- // `try_register_dtor` where it is originally a Key<T> coming from `self`,
237
- // making it non-NUL and of the correct type.
238
- //
239
- // Right before we run the user destructor be sure to set the
240
- // `Option<T>` to `None`, and `dtor_state` to `RunningOrHasRun`. This
241
- // causes future calls to `get` to run `try_initialize_drop` again,
242
- // which will now fail, and return `None`.
243
- //
244
- // Wrap the call in a catch to ensure unwinding is caught in the event
245
- // a panic takes place in a destructor.
246
- if let Err ( _) = panic:: catch_unwind ( panic:: AssertUnwindSafe ( || unsafe {
247
- let value = ( * ptr) . inner . take ( ) ;
248
- ( * ptr) . dtor_state . set ( DtorState :: RunningOrHasRun ) ;
249
- drop ( value) ;
250
- } ) ) {
251
- rtabort ! ( "thread local panicked on drop" ) ;
252
- }
227
+ // SAFETY:
228
+ //
229
+ // The pointer `ptr` has been built just above and comes from
230
+ // `try_register_dtor` where it is originally a Key<T> coming from `self`,
231
+ // making it non-NUL and of the correct type.
232
+ //
233
+ // Right before we run the user destructor be sure to set the
234
+ // `Option<T>` to `None`, and `dtor_state` to `RunningOrHasRun`. This
235
+ // causes future calls to `get` to run `try_initialize_drop` again,
236
+ // which will now fail, and return `None`.
237
+ //
238
+ // Wrap the call in a catch to ensure unwinding is caught in the event
239
+ // a panic takes place in a destructor.
240
+ if let Err ( _) = panic:: catch_unwind ( panic:: AssertUnwindSafe ( || unsafe {
241
+ let value = ( * ptr) . inner . take ( ) ;
242
+ ( * ptr) . dtor_state . set ( DtorState :: RunningOrHasRun ) ;
243
+ drop ( value) ;
244
+ } ) ) {
245
+ rtabort ! ( "thread local panicked on drop" ) ;
253
246
}
254
247
}
0 commit comments