@@ -33,28 +33,29 @@ pub macro thread_local_inner {
33
33
// 1 == dtor registered, dtor not run
34
34
// 2 == dtor registered and is running or has run
35
35
#[ thread_local]
36
- static mut STATE : $crate:: primitive:: u8 = 0 ;
36
+ static STATE : $crate:: cell :: Cell < $crate :: primitive:: u8 > = $crate :: cell :: Cell :: new ( 0 ) ;
37
37
38
+ // Safety: Performs `drop_in_place(ptr as *mut $t)`, and requires
39
+ // all that comes with it.
38
40
unsafe extern "C" fn destroy ( ptr : * mut $crate:: primitive:: u8 ) {
39
- let ptr = ptr as * mut $t;
40
-
41
- unsafe {
42
- $crate:: debug_assert_eq!( STATE , 1 ) ;
43
- STATE = 2 ;
44
- $crate:: ptr:: drop_in_place ( ptr) ;
45
- }
41
+ $crate:: thread:: local_impl:: abort_on_dtor_unwind ( || {
42
+ let old_state = STATE . replace ( 2 ) ;
43
+ $crate:: debug_assert_eq!( old_state, 1 ) ;
44
+ // Safety: safety requirement is passed on to caller.
45
+ unsafe { $crate:: ptr:: drop_in_place ( ptr. cast :: < $t> ( ) ) ; }
46
+ } ) ;
46
47
}
47
48
48
49
unsafe {
49
- match STATE {
50
+ match STATE . get ( ) {
50
51
// 0 == we haven't registered a destructor, so do
51
52
// so now.
52
53
0 => {
53
54
$crate:: thread:: local_impl:: Key :: < $t> :: register_dtor (
54
55
$crate:: ptr:: addr_of_mut!( VAL ) as * mut $crate:: primitive:: u8 ,
55
56
destroy,
56
57
) ;
57
- STATE = 1 ;
58
+ STATE . set ( 1 ) ;
58
59
$crate:: option:: Option :: Some ( & VAL )
59
60
}
60
61
// 1 == the destructor is registered and the value
@@ -148,7 +149,6 @@ impl<T> fmt::Debug for Key<T> {
148
149
f. debug_struct ( "Key" ) . finish_non_exhaustive ( )
149
150
}
150
151
}
151
-
152
152
impl < T > Key < T > {
153
153
pub const fn new ( ) -> Key < T > {
154
154
Key { inner : LazyKeyInner :: new ( ) , dtor_state : Cell :: new ( DtorState :: Unregistered ) }
0 commit comments