@@ -16,30 +16,22 @@ pub macro thread_local_inner {
1616 } ,
1717
1818 // used to generate the `LocalKey` value for `thread_local!`
19- ( @key $t: ty, $init: expr) => {
20- {
21- #[ inline]
22- fn __init( ) -> $t { $init }
19+ ( @key $t: ty, $init: expr) => { {
20+ #[ inline]
21+ fn __init( ) -> $t { $init }
2322
24- // `#[inline] does not work on windows-gnu due to linking errors around dllimports.
25- // See https://github.com/rust-lang/rust/issues/109797.
26- #[ cfg_attr( not( windows) , inline) ]
27- unsafe fn __getit (
28- init : $crate:: option:: Option < & mut $crate:: option:: Option < $t> > ,
29- ) -> $crate:: option:: Option < & ' static $t> {
30- use $crate:: thread:: local_impl:: Key ;
31-
32- static __KEY: Key < $t> = Key :: new ( ) ;
33- unsafe {
34- __KEY. get ( init, __init)
35- }
36- }
23+ unsafe {
24+ use $crate:: thread:: LocalKey ;
25+ use $crate:: thread:: local_impl:: Key ;
3726
38- unsafe {
39- $crate:: thread:: LocalKey :: new ( __getit)
40- }
27+ // Inlining does not work on windows-gnu due to linking errors around
28+ // dllimports. See https://github.com/rust-lang/rust/issues/109797.
29+ LocalKey :: new ( #[ cfg_attr( windows, inline( never) ) ] |init| {
30+ static VAL : Key < $t> = Key :: new ( ) ;
31+ VAL . get ( init, __init)
32+ } )
4133 }
42- } ,
34+ } } ,
4335 ( $( #[ $attr: meta] ) * $vis: vis $name: ident, $t: ty, $( $init: tt) * ) => {
4436 $( #[ $attr] ) * $vis const $name: $crate:: thread:: LocalKey <$t> =
4537 $crate:: thread:: local_impl:: thread_local_inner!( @key $t, $( $init) * ) ;
@@ -67,38 +59,33 @@ impl<T: 'static> Key<T> {
6759 Key { os : OsKey :: new ( Some ( destroy_value :: < T > ) ) , marker : PhantomData }
6860 }
6961
70- /// Get the value associated with this key, initializating it if necessary.
62+ /// Get a pointer to the TLS value, potentially initializing it with the
63+ /// provided parameters. If the TLS variable has been destroyed, a null
64+ /// pointer is returned.
7165 ///
72- /// # Safety
73- /// * the returned reference must not be used after recursive initialization
74- /// or thread destruction occurs.
75- pub unsafe fn get (
76- & ' static self ,
77- i : Option < & mut Option < T > > ,
78- f : impl FnOnce ( ) -> T ,
79- ) -> Option < & ' static T > {
66+ /// The resulting pointer may not be used after reentrant inialialization
67+ /// or thread destruction has occurred.
68+ pub fn get ( & ' static self , i : Option < & mut Option < T > > , f : impl FnOnce ( ) -> T ) -> * const T {
8069 // SAFETY: (FIXME: get should actually be safe)
8170 let ptr = unsafe { self . os . get ( ) as * mut Value < T > } ;
8271 if ptr. addr ( ) > 1 {
8372 // SAFETY: the check ensured the pointer is safe (its destructor
8473 // is not running) + it is coming from a trusted source (self).
85- unsafe { Some ( & ( * ptr) . value ) }
74+ unsafe { & ( * ptr) . value }
8675 } else {
87- // SAFETY: At this point we are sure we have no value and so
88- // initializing (or trying to) is safe.
89- unsafe { self . try_initialize ( ptr, i, f) }
76+ self . try_initialize ( ptr, i, f)
9077 }
9178 }
9279
93- unsafe fn try_initialize (
80+ fn try_initialize (
9481 & ' static self ,
9582 ptr : * mut Value < T > ,
9683 i : Option < & mut Option < T > > ,
9784 f : impl FnOnce ( ) -> T ,
98- ) -> Option < & ' static T > {
85+ ) -> * const T {
9986 if ptr. addr ( ) == 1 {
10087 // destructor is running
101- return None ;
88+ return ptr :: null ( ) ;
10289 }
10390
10491 let value = i. and_then ( Option :: take) . unwrap_or_else ( f) ;
@@ -119,7 +106,7 @@ impl<T: 'static> Key<T> {
119106 }
120107
121108 // SAFETY: We just created this value above.
122- unsafe { Some ( & ( * ptr) . value ) }
109+ unsafe { & ( * ptr) . value }
123110 }
124111}
125112
0 commit comments