|
15 | 15 | use std::ffi::c_void;
|
16 | 16 | use std::sync::OnceLock;
|
17 | 17 |
|
18 |
| -pub type ThreadAtexitFn = unsafe extern "C" fn(*mut c_void, *mut c_void, *mut c_void); |
19 |
| - |
20 | 18 | static SYSTEM_THREAD_ATEXIT: OnceLock<Option<ThreadAtexitFn>> = OnceLock::new();
|
21 | 19 | static HOT_RELOADING_ENABLED: OnceLock<bool> = OnceLock::new();
|
22 | 20 |
|
23 |
| -fn system_thread_atexit() -> &'static Option<ThreadAtexitFn> { |
24 |
| - SYSTEM_THREAD_ATEXIT.get_or_init(|| unsafe { |
25 |
| - let name = c"__cxa_thread_atexit_impl".as_ptr(); |
26 |
| - std::mem::transmute(libc::dlsym(libc::RTLD_NEXT, name)) |
27 |
| - }) |
28 |
| -} |
29 |
| - |
30 |
| -pub fn enable_hot_reload() { |
31 |
| - // If hot reloading is enabled then we should properly unload the library, so this will only be called once. |
32 |
| - HOT_RELOADING_ENABLED |
33 |
| - .set(true) |
34 |
| - .expect("hot reloading should only be set once") |
35 |
| -} |
36 |
| - |
37 |
| -pub fn disable_hot_reload() { |
38 |
| - // If hot reloading is disabled then we may call this method multiple times. |
39 |
| - _ = HOT_RELOADING_ENABLED.set(false) |
40 |
| -} |
41 |
| - |
42 | 21 | pub fn default_set_hot_reload() {
|
43 | 22 | // By default, we enable hot reloading for debug builds, as it's likely that the user may want hot reloading in debug builds.
|
44 | 23 | // Release builds however should avoid leaking memory, so we disable hot reloading support by default.
|
| 24 | + // In the future, this might consider the .gdextension `is_reloadable` flag, or whether Godot is using an editor or export build. |
45 | 25 | if cfg!(debug_assertions) {
|
46 | 26 | enable_hot_reload()
|
47 | 27 | } else {
|
48 | 28 | disable_hot_reload()
|
49 | 29 | }
|
50 | 30 | }
|
51 | 31 |
|
52 |
| -fn is_hot_reload_enabled() -> bool { |
| 32 | +// ---------------------------------------------------------------------------------------------------------------------------------------------- |
| 33 | +// Publicly accessible |
| 34 | + |
| 35 | +#[macro_export] |
| 36 | +macro_rules! register_hot_reload_workaround { |
| 37 | + () => { |
| 38 | + #[no_mangle] |
| 39 | + #[doc(hidden)] |
| 40 | + pub unsafe extern "C" fn __cxa_thread_atexit_impl( |
| 41 | + func: *mut ::std::ffi::c_void, |
| 42 | + obj: *mut ::std::ffi::c_void, |
| 43 | + dso_symbol: *mut ::std::ffi::c_void, |
| 44 | + ) { |
| 45 | + $crate::linux_reload_workaround::thread_atexit(func, obj, dso_symbol); |
| 46 | + } |
| 47 | + }; |
| 48 | +} |
| 49 | + |
| 50 | +type ThreadAtexitFn = unsafe extern "C" fn(*mut c_void, *mut c_void, *mut c_void); |
| 51 | + |
| 52 | +pub fn system_thread_atexit() -> &'static Option<ThreadAtexitFn> { |
| 53 | + SYSTEM_THREAD_ATEXIT.get_or_init(|| unsafe { |
| 54 | + let name = c"__cxa_thread_atexit_impl".as_ptr(); |
| 55 | + std::mem::transmute(libc::dlsym(libc::RTLD_NEXT, name)) |
| 56 | + }) |
| 57 | +} |
| 58 | + |
| 59 | +pub fn is_hot_reload_enabled() -> bool { |
53 | 60 | // Assume hot reloading is disabled unless something else has been specified already. This is the better default as thread local storage
|
54 | 61 | // destructors exist for good reasons.
|
55 | 62 | // This is needed for situations like unit-tests, where we may create TLS-destructors without explicitly calling any of the methods
|
@@ -78,17 +85,17 @@ pub unsafe fn thread_atexit(func: *mut c_void, obj: *mut c_void, dso_symbol: *mu
|
78 | 85 | }
|
79 | 86 | }
|
80 | 87 |
|
81 |
| -#[macro_export] |
82 |
| -macro_rules! register_hot_reload_workaround { |
83 |
| - () => { |
84 |
| - #[no_mangle] |
85 |
| - #[doc(hidden)] |
86 |
| - pub unsafe extern "C" fn __cxa_thread_atexit_impl( |
87 |
| - func: *mut ::std::ffi::c_void, |
88 |
| - obj: *mut ::std::ffi::c_void, |
89 |
| - dso_symbol: *mut ::std::ffi::c_void, |
90 |
| - ) { |
91 |
| - $crate::linux_reload_workaround::thread_atexit(func, obj, dso_symbol); |
92 |
| - } |
93 |
| - }; |
| 88 | +// ---------------------------------------------------------------------------------------------------------------------------------------------- |
| 89 | +// Implementation |
| 90 | + |
| 91 | +fn enable_hot_reload() { |
| 92 | + // If hot reloading is enabled then we should properly unload the library, so this will only be called once. |
| 93 | + HOT_RELOADING_ENABLED |
| 94 | + .set(true) |
| 95 | + .expect("hot reloading should only be set once") |
| 96 | +} |
| 97 | + |
| 98 | +fn disable_hot_reload() { |
| 99 | + // If hot reloading is disabled then we may call this method multiple times. |
| 100 | + _ = HOT_RELOADING_ENABLED.set(false) |
94 | 101 | }
|
0 commit comments