mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 23:12:02 +00:00
Windows thread-local keyless drop
`#[thread_local]` allows us to maintain a per-thread list of destructors. This also avoids the need to synchronize global data (which is particularly tricky within the TLS callback function).
This commit is contained in:
parent
68b554e6af
commit
9212f4070e
@ -1,4 +1,39 @@
|
||||
//! Implements thread-local destructors that are not associated with any
|
||||
//! particular data.
|
||||
|
||||
#![unstable(feature = "thread_local_internals", issue = "none")]
|
||||
#![cfg(target_thread_local)]
|
||||
use super::c;
|
||||
|
||||
pub use crate::sys_common::thread_local_dtor::register_dtor_fallback as register_dtor;
|
||||
// Using a per-thread list avoids the problems in synchronizing global state.
|
||||
#[thread_local]
|
||||
static mut DESTRUCTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new();
|
||||
|
||||
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
|
||||
DESTRUCTORS.push((t, dtor));
|
||||
}
|
||||
|
||||
// See windows/thread_local_keys.rs for an explanation of this callback function.
|
||||
// The short version is that all the function pointers in the `.CRT$XL*` array
|
||||
// will be called whenever a thread or process starts or ends.
|
||||
|
||||
#[link_section = ".CRT$XLD"]
|
||||
#[doc(hidden)]
|
||||
#[used]
|
||||
pub static TLS_CALLBACK: unsafe extern "system" fn(c::LPVOID, c::DWORD, c::LPVOID) = tls_callback;
|
||||
|
||||
unsafe extern "system" fn tls_callback(_: c::LPVOID, reason: c::DWORD, _: c::LPVOID) {
|
||||
if reason == c::DLL_THREAD_DETACH || reason == c::DLL_PROCESS_DETACH {
|
||||
// Drop all the destructors.
|
||||
//
|
||||
// Note: While this is potentially an infinite loop, it *should* be
|
||||
// the case that this loop always terminates because we provide the
|
||||
// guarantee that a TLS key cannot be set after it is flagged for
|
||||
// destruction.
|
||||
while let Some((ptr, dtor)) = DESTRUCTORS.pop() {
|
||||
(dtor)(ptr);
|
||||
}
|
||||
// We're done so free the memory.
|
||||
DESTRUCTORS.shrink_to_fit();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user