1 //! Thread-local destructor
3 //! Besides thread-local "keys" (pointer-sized non-addressable thread-local store
4 //! with an associated destructor), many platforms also provide thread-local
5 //! destructors that are not associated with any particular data. These are
6 //! often more efficient.
8 //! This module provides a fallback implementation for that interface, based
9 //! on the less efficient thread-local "keys". Each platform provides
10 //! a `thread_local_dtor` module which will either re-export the fallback,
11 //! or implement something more efficient.
13 #![unstable(feature = "thread_local_internals", issue = "none")]
17 use crate::sys_common::thread_local_key::StaticKey;
19 pub unsafe fn register_dtor_fallback(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
20 // The fallback implementation uses a vanilla OS-based TLS key to track
21 // the list of destructors that need to be run for this thread. The key
22 // then has its own destructor which runs all the other destructors.
24 // The destructor for DTORS is a little special in that it has a `while`
25 // loop to continuously drain the list of registered destructors. It
26 // *should* be the case that this loop always terminates because we
27 // provide the guarantee that a TLS key cannot be set after it is
28 // flagged for destruction.
30 static DTORS: StaticKey = StaticKey::new(Some(run_dtors));
31 type List = Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>;
32 if DTORS.get().is_null() {
33 let v: Box<List> = box Vec::new();
34 DTORS.set(Box::into_raw(v) as *mut u8);
36 let list: &mut List = &mut *(DTORS.get() as *mut List);
39 unsafe extern "C" fn run_dtors(mut ptr: *mut u8) {
40 while !ptr.is_null() {
41 let list: Box<List> = Box::from_raw(ptr as *mut List);
42 for (ptr, dtor) in list.into_iter() {
46 DTORS.set(ptr::null_mut());