use std::ffi::c_void;
use std::sync::OnceLock;
static SYSTEM_THREAD_ATEXIT: OnceLock<Option<ThreadAtexitFn>> = OnceLock::new();
static HOT_RELOADING_ENABLED: OnceLock<bool> = OnceLock::new();
pub fn default_set_hot_reload() {
if cfg!(debug_assertions) {
enable_hot_reload()
} else {
disable_hot_reload()
}
}
#[macro_export]
macro_rules! register_hot_reload_workaround {
() => {
#[unsafe(no_mangle)]
#[doc(hidden)]
pub unsafe extern "C" fn __cxa_thread_atexit_impl(
func: *mut ::std::ffi::c_void,
obj: *mut ::std::ffi::c_void,
dso_symbol: *mut ::std::ffi::c_void,
) {
$crate::linux_reload_workaround::thread_atexit(func, obj, dso_symbol);
}
};
}
type ThreadAtexitFn = unsafe extern "C" fn(*mut c_void, *mut c_void, *mut c_void);
pub fn system_thread_atexit() -> &'static Option<ThreadAtexitFn> {
SYSTEM_THREAD_ATEXIT.get_or_init(|| unsafe {
let name = c"__cxa_thread_atexit_impl".as_ptr();
std::mem::transmute(libc::dlsym(libc::RTLD_NEXT, name))
})
}
pub fn is_hot_reload_enabled() -> bool {
*HOT_RELOADING_ENABLED.get_or_init(|| false)
}
pub unsafe fn thread_atexit(func: *mut c_void, obj: *mut c_void, dso_symbol: *mut c_void) {
if is_hot_reload_enabled() {
} else if let Some(system_thread_atexit) = *system_thread_atexit() {
unsafe { system_thread_atexit(func, obj, dso_symbol) };
} else {
}
}
fn enable_hot_reload() {
HOT_RELOADING_ENABLED
.set(true)
.expect("hot reloading should only be set once")
}
fn disable_hot_reload() {
_ = HOT_RELOADING_ENABLED.set(false)
}