]>
Commit | Line | Data |
---|---|---|
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")] | |
14 | #![allow(dead_code)] // sys isn't exported yet | |
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 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 | } |