Skip to content

Commit 9e81485

Browse files
authored
Merge pull request #1253 from TitanNano/jovan/android_main_thread
Godot can use a different "main thread" for the main loop
2 parents 72d6d17 + bc5c143 commit 9e81485

File tree

3 files changed

+31
-2
lines changed

3 files changed

+31
-2
lines changed

godot-core/src/init/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ unsafe fn gdext_on_level_init(level: InitLevel) {
158158
unsafe { sys::load_class_method_table(level) };
159159

160160
match level {
161+
InitLevel::Servers => {
162+
// SAFETY: called from the main thread, sys::initialized has already been called.
163+
unsafe { sys::discover_main_thread() };
164+
}
161165
InitLevel::Scene => {
162166
// SAFETY: On the main thread, api initialized, `Scene` was initialized above.
163167
unsafe { ensure_godot_features_compatible() };

godot-ffi/src/binding/single_threaded.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,7 @@ impl BindingStorage {
123123

124124
// We only check if we are in the main thread in debug builds if we aren't building for a non-threaded Godot build,
125125
// since we could otherwise assume there won't be multi-threading.
126-
// TODO: figure out why the panic happens on Android, and how to resolve it. See https://github.com/godot-rust/gdext/pull/780.
127-
#[cfg(all(debug_assertions, not(wasm_nothreads), not(target_os = "android")))]
126+
#[cfg(all(debug_assertions, not(wasm_nothreads)))]
128127
{
129128
if !crate::is_main_thread() {
130129
// If a binding is accessed the first time, this will panic and start unwinding. It can then happen that during unwinding,

godot-ffi/src/lib.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,32 @@ pub fn is_main_thread() -> bool {
447447
}
448448
}
449449

450+
/// Assign the current thread id to be the main thread.
451+
///
452+
/// This is required for platforms on which Godot runs the main loop on a different thread than the thread the library was loaded on.
453+
/// Android is one such platform.
454+
///
455+
/// # Safety
456+
///
457+
/// - must only be called after [`initialize`] has been called.
458+
pub unsafe fn discover_main_thread() {
459+
#[cfg(not(wasm_nothreads))]
460+
{
461+
if is_main_thread() {
462+
// we don't have to do anything if the current thread is already the main thread.
463+
return;
464+
}
465+
466+
let thread_id = std::thread::current().id();
467+
468+
// SAFETY: initialize must have already been called before this function is called. By clearing and setting the cell again we can reinitialize it.
469+
unsafe {
470+
MAIN_THREAD_ID.clear();
471+
MAIN_THREAD_ID.set(thread_id);
472+
}
473+
}
474+
}
475+
450476
// ----------------------------------------------------------------------------------------------------------------------------------------------
451477
// Macros to access low-level function bindings
452478

0 commit comments

Comments
 (0)