]> git.proxmox.com Git - rustc.git/blame - library/std/src/sys_common/thread_local_dtor.rs
New upstream version 1.63.0+dfsg1
[rustc.git] / library / std / src / sys_common / thread_local_dtor.rs
CommitLineData
3dfed10e
XL
1//! Thread-local destructor
2//!
6a06907d 3//! Besides thread-local "keys" (pointer-sized non-addressable thread-local store
3dfed10e
XL
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")]
923072b8 14#![allow(dead_code)]
3dfed10e
XL
15
16use crate::ptr;
17use crate::sys_common::thread_local_key::StaticKey;
18
19pub 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 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}