summaryrefslogtreecommitdiffstats
path: root/library/std/src/sys/common/thread_local/fast_local.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/sys/common/thread_local/fast_local.rs')
-rw-r--r--library/std/src/sys/common/thread_local/fast_local.rs22
1 files changed, 11 insertions, 11 deletions
diff --git a/library/std/src/sys/common/thread_local/fast_local.rs b/library/std/src/sys/common/thread_local/fast_local.rs
index 447044a79..bc5da1a18 100644
--- a/library/std/src/sys/common/thread_local/fast_local.rs
+++ b/library/std/src/sys/common/thread_local/fast_local.rs
@@ -33,20 +33,21 @@ pub macro thread_local_inner {
// 1 == dtor registered, dtor not run
// 2 == dtor registered and is running or has run
#[thread_local]
- static mut STATE: $crate::primitive::u8 = 0;
+ static STATE: $crate::cell::Cell<$crate::primitive::u8> = $crate::cell::Cell::new(0);
+ // Safety: Performs `drop_in_place(ptr as *mut $t)`, and requires
+ // all that comes with it.
unsafe extern "C" fn destroy(ptr: *mut $crate::primitive::u8) {
- let ptr = ptr as *mut $t;
-
- unsafe {
- $crate::debug_assert_eq!(STATE, 1);
- STATE = 2;
- $crate::ptr::drop_in_place(ptr);
- }
+ $crate::thread::local_impl::abort_on_dtor_unwind(|| {
+ let old_state = STATE.replace(2);
+ $crate::debug_assert_eq!(old_state, 1);
+ // Safety: safety requirement is passed on to caller.
+ unsafe { $crate::ptr::drop_in_place(ptr.cast::<$t>()); }
+ });
}
unsafe {
- match STATE {
+ match STATE.get() {
// 0 == we haven't registered a destructor, so do
// so now.
0 => {
@@ -54,7 +55,7 @@ pub macro thread_local_inner {
$crate::ptr::addr_of_mut!(VAL) as *mut $crate::primitive::u8,
destroy,
);
- STATE = 1;
+ STATE.set(1);
$crate::option::Option::Some(&VAL)
}
// 1 == the destructor is registered and the value
@@ -148,7 +149,6 @@ impl<T> fmt::Debug for Key<T> {
f.debug_struct("Key").finish_non_exhaustive()
}
}
-
impl<T> Key<T> {
pub const fn new() -> Key<T> {
Key { inner: LazyKeyInner::new(), dtor_state: Cell::new(DtorState::Unregistered) }