@@ -173,200 +173,6 @@ macro_rules! thread_local {
173
173
) ;
174
174
}
175
175
176
- #[ doc( hidden) ]
177
- #[ unstable( feature = "thread_local_internals" , reason = "should not be necessary" , issue = "none" ) ]
178
- #[ macro_export]
179
- #[ allow_internal_unstable( thread_local_internals, cfg_target_thread_local, thread_local) ]
180
- #[ allow_internal_unsafe]
181
- macro_rules! __thread_local_inner {
182
- // used to generate the `LocalKey` value for const-initialized thread locals
183
- ( @key $t: ty, const $init: expr) => { {
184
- #[ cfg_attr( not( windows) , inline) ] // see comments below
185
- #[ deny( unsafe_op_in_unsafe_fn) ]
186
- unsafe fn __getit(
187
- _init: $crate:: option:: Option <& mut $crate:: option:: Option <$t>>,
188
- ) -> $crate:: option:: Option <& ' static $t> {
189
- const INIT_EXPR : $t = $init;
190
-
191
- // wasm without atomics maps directly to `static mut`, and dtors
192
- // aren't implemented because thread dtors aren't really a thing
193
- // on wasm right now
194
- //
195
- // FIXME(#84224) this should come after the `target_thread_local`
196
- // block.
197
- #[ cfg( all( target_family = "wasm" , not( target_feature = "atomics" ) ) ) ]
198
- {
199
- static mut VAL : $t = INIT_EXPR ;
200
- unsafe { $crate:: option:: Option :: Some ( & VAL ) }
201
- }
202
-
203
- // If the platform has support for `#[thread_local]`, use it.
204
- #[ cfg( all(
205
- target_thread_local,
206
- not( all( target_family = "wasm" , not( target_feature = "atomics" ) ) ) ,
207
- ) ) ]
208
- {
209
- #[ thread_local]
210
- static mut VAL : $t = INIT_EXPR ;
211
-
212
- // If a dtor isn't needed we can do something "very raw" and
213
- // just get going.
214
- if !$crate:: mem:: needs_drop:: <$t>( ) {
215
- unsafe {
216
- return $crate:: option:: Option :: Some ( & VAL )
217
- }
218
- }
219
-
220
- // 0 == dtor not registered
221
- // 1 == dtor registered, dtor not run
222
- // 2 == dtor registered and is running or has run
223
- #[ thread_local]
224
- static mut STATE : $crate:: primitive:: u8 = 0 ;
225
-
226
- unsafe extern "C" fn destroy( ptr: * mut $crate:: primitive:: u8 ) {
227
- let ptr = ptr as * mut $t;
228
-
229
- unsafe {
230
- $crate:: debug_assert_eq!( STATE , 1 ) ;
231
- STATE = 2 ;
232
- $crate:: ptr:: drop_in_place( ptr) ;
233
- }
234
- }
235
-
236
- unsafe {
237
- match STATE {
238
- // 0 == we haven't registered a destructor, so do
239
- // so now.
240
- 0 => {
241
- $crate:: thread:: __FastLocalKeyInner:: <$t>:: register_dtor(
242
- $crate:: ptr:: addr_of_mut!( VAL ) as * mut $crate:: primitive:: u8 ,
243
- destroy,
244
- ) ;
245
- STATE = 1 ;
246
- $crate:: option:: Option :: Some ( & VAL )
247
- }
248
- // 1 == the destructor is registered and the value
249
- // is valid, so return the pointer.
250
- 1 => $crate:: option:: Option :: Some ( & VAL ) ,
251
- // otherwise the destructor has already run, so we
252
- // can't give access.
253
- _ => $crate:: option:: Option :: None ,
254
- }
255
- }
256
- }
257
-
258
- // On platforms without `#[thread_local]` we fall back to the
259
- // same implementation as below for os thread locals.
260
- #[ cfg( all(
261
- not( target_thread_local) ,
262
- not( all( target_family = "wasm" , not( target_feature = "atomics" ) ) ) ,
263
- ) ) ]
264
- {
265
- #[ inline]
266
- const fn __init( ) -> $t { INIT_EXPR }
267
- static __KEY: $crate:: thread:: __OsLocalKeyInner<$t> =
268
- $crate:: thread:: __OsLocalKeyInner:: new( ) ;
269
- #[ allow( unused_unsafe) ]
270
- unsafe {
271
- __KEY. get( move || {
272
- if let $crate:: option:: Option :: Some ( init) = _init {
273
- if let $crate:: option:: Option :: Some ( value) = init. take( ) {
274
- return value;
275
- } else if $crate:: cfg!( debug_assertions) {
276
- $crate:: unreachable!( "missing initial value" ) ;
277
- }
278
- }
279
- __init( )
280
- } )
281
- }
282
- }
283
- }
284
-
285
- unsafe {
286
- $crate:: thread:: LocalKey :: new( __getit)
287
- }
288
- } } ;
289
-
290
- // used to generate the `LocalKey` value for `thread_local!`
291
- ( @key $t: ty, $init: expr) => {
292
- {
293
- #[ inline]
294
- fn __init( ) -> $t { $init }
295
-
296
- // When reading this function you might ask "why is this inlined
297
- // everywhere other than Windows?", and that's a very reasonable
298
- // question to ask. The short story is that it segfaults rustc if
299
- // this function is inlined. The longer story is that Windows looks
300
- // to not support `extern` references to thread locals across DLL
301
- // boundaries. This appears to at least not be supported in the ABI
302
- // that LLVM implements.
303
- //
304
- // Because of this we never inline on Windows, but we do inline on
305
- // other platforms (where external references to thread locals
306
- // across DLLs are supported). A better fix for this would be to
307
- // inline this function on Windows, but only for "statically linked"
308
- // components. For example if two separately compiled rlibs end up
309
- // getting linked into a DLL then it's fine to inline this function
310
- // across that boundary. It's only not fine to inline this function
311
- // across a DLL boundary. Unfortunately rustc doesn't currently
312
- // have this sort of logic available in an attribute, and it's not
313
- // clear that rustc is even equipped to answer this (it's more of a
314
- // Cargo question kinda). This means that, unfortunately, Windows
315
- // gets the pessimistic path for now where it's never inlined.
316
- //
317
- // The issue of "should enable on Windows sometimes" is #84933
318
- #[ cfg_attr( not( windows) , inline) ]
319
- unsafe fn __getit(
320
- init: $crate:: option:: Option <& mut $crate:: option:: Option <$t>>,
321
- ) -> $crate:: option:: Option <& ' static $t> {
322
- #[ cfg( all( target_family = "wasm" , not( target_feature = "atomics" ) ) ) ]
323
- static __KEY: $crate:: thread:: __StaticLocalKeyInner<$t> =
324
- $crate:: thread:: __StaticLocalKeyInner:: new( ) ;
325
-
326
- #[ thread_local]
327
- #[ cfg( all(
328
- target_thread_local,
329
- not( all( target_family = "wasm" , not( target_feature = "atomics" ) ) ) ,
330
- ) ) ]
331
- static __KEY: $crate:: thread:: __FastLocalKeyInner<$t> =
332
- $crate:: thread:: __FastLocalKeyInner:: new( ) ;
333
-
334
- #[ cfg( all(
335
- not( target_thread_local) ,
336
- not( all( target_family = "wasm" , not( target_feature = "atomics" ) ) ) ,
337
- ) ) ]
338
- static __KEY: $crate:: thread:: __OsLocalKeyInner<$t> =
339
- $crate:: thread:: __OsLocalKeyInner:: new( ) ;
340
-
341
- // FIXME: remove the #[allow(...)] marker when macros don't
342
- // raise warning for missing/extraneous unsafe blocks anymore.
343
- // See https://github.com/rust-lang/rust/issues/74838.
344
- #[ allow( unused_unsafe) ]
345
- unsafe {
346
- __KEY. get( move || {
347
- if let $crate:: option:: Option :: Some ( init) = init {
348
- if let $crate:: option:: Option :: Some ( value) = init. take( ) {
349
- return value;
350
- } else if $crate:: cfg!( debug_assertions) {
351
- $crate:: unreachable!( "missing default value" ) ;
352
- }
353
- }
354
- __init( )
355
- } )
356
- }
357
- }
358
-
359
- unsafe {
360
- $crate:: thread:: LocalKey :: new( __getit)
361
- }
362
- }
363
- } ;
364
- ( $( #[ $attr: meta] ) * $vis: vis $name: ident, $t: ty, $( $init: tt) * ) => {
365
- $( #[ $attr] ) * $vis const $name: $crate:: thread:: LocalKey <$t> =
366
- $crate:: __thread_local_inner!( @key $t, $( $init) * ) ;
367
- }
368
- }
369
-
370
176
/// An error returned by [`LocalKey::try_with`](struct.LocalKey.html#method.try_with).
371
177
#[ stable( feature = "thread_local_try_with" , since = "1.26.0" ) ]
372
178
#[ non_exhaustive]
0 commit comments