std/sys/thread_local/destructors/
list.rs

1use crate::cell::RefCell;
2use crate::sys::thread_local::guard;
3
4#[thread_local]
5static DTORS: RefCell<Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>> = RefCell::new(Vec::new());
6
7pub unsafe fn register(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
8    let Ok(mut dtors) = DTORS.try_borrow_mut() else {
9        // This point can only be reached if the global allocator calls this
10        // function again.
11        // FIXME: maybe use the system allocator instead?
12        rtabort!("the global allocator may not use TLS with destructors");
13    };
14
15    guard::enable();
16
17    dtors.push((t, dtor));
18}
19
20/// The [`guard`] module contains platform-specific functions which will run this
21/// function on thread exit if [`guard::enable`] has been called.
22///
23/// # Safety
24///
25/// May only be run on thread exit to guarantee that there are no live references
26/// to TLS variables while they are destroyed.
27pub unsafe fn run() {
28    loop {
29        let mut dtors = DTORS.borrow_mut();
30        match dtors.pop() {
31            Some((t, dtor)) => {
32                drop(dtors);
33                unsafe {
34                    dtor(t);
35                }
36            }
37            None => {
38                // Free the list memory.
39                *dtors = Vec::new();
40                break;
41            }
42        }
43    }
44}