]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys_common/thread_local_dtor.rs
refactor[std]: do not use box syntax
[rust.git] / library / std / src / sys_common / thread_local_dtor.rs
1 //! Thread-local destructor
2 //!
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.
7 //!
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.
12
13 #![unstable(feature = "thread_local_internals", issue = "none")]
14 #![allow(dead_code)]
15
16 use crate::ptr;
17 use crate::sys_common::thread_local_key::StaticKey;
18
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.
23     //
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.
29
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::new(Vec::new());
34         DTORS.set(Box::into_raw(v) as *mut u8);
35     }
36     let list: &mut List = &mut *(DTORS.get() as *mut List);
37     list.push((t, dtor));
38
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() {
43                 dtor(ptr);
44             }
45             ptr = DTORS.get();
46             DTORS.set(ptr::null_mut());
47         }
48     }
49 }