std/sys/thread_local/native/
eager.rs1use crate::cell::{Cell, UnsafeCell};
2use crate::ptr::{self, drop_in_place};
3use crate::sys::thread_local::{abort_on_dtor_unwind, destructors};
4
5#[derive(Clone, Copy)]
6enum State {
7 Alive = 0,
8 Unregistered,
9 Destroyed,
10}
11
12#[allow(missing_debug_implementations)]
13#[repr(C)]
14pub struct Storage<T> {
15 val: UnsafeCell<T>,
17 state: Cell<State>,
18}
19
20impl<T> Storage<T> {
21 pub const fn new(val: T) -> Storage<T> {
22 Storage { state: Cell::new(State::Unregistered), val: UnsafeCell::new(val) }
23 }
24
25 #[inline]
34 pub unsafe fn get(&self) -> *const T {
35 if let State::Alive = self.state.get() {
36 self.val.get()
37 } else {
38 unsafe { self.get_or_init_slow() }
39 }
40 }
41
42 #[cold]
43 unsafe fn get_or_init_slow(&self) -> *const T {
44 match self.state.get() {
45 State::Unregistered => {}
46 State::Alive => return self.val.get(),
47 State::Destroyed => return ptr::null(),
48 }
49
50 unsafe {
55 destructors::register(ptr::from_ref(self).cast_mut().cast(), destroy::<T>);
56 }
57
58 self.state.set(State::Alive);
59 self.val.get()
60 }
61}
62
63unsafe extern "C" fn destroy<T>(ptr: *mut u8) {
71 abort_on_dtor_unwind(|| {
73 let storage = unsafe { &*(ptr as *const Storage<T>) };
74 storage.state.set(State::Destroyed);
77 unsafe {
78 drop_in_place(storage.val.get());
79 }
80 })
81}