Support multithreading for NativeScriptLanguage

Godot may call property setters from non-main thread when an object is
loaded in the edtior. This means NativeScriptLanguage could be accessed
from different threads, but it was not designed for thread-safety.
Besides, previous behaviour made it so that godot_nativescript_init and
godot_gdnative_init could be invoked from non-main thread, while
godot_gdnative_thread is always invoked on the main thread. This may
not be expected by the binding library.

This commit defers native library initialization to the main thread and
adds godot_nativescript_thread_enter and godot_nativescript_thread_exit
callbacks to make a binding library aware of foreign threads.
This commit is contained in:
Ruslan Mustakov 2017-07-26 15:58:12 +07:00
parent f55211ae0d
commit 7f32023a1a
3 changed files with 211 additions and 38 deletions

View file

@ -41,6 +41,10 @@
#include "godot_nativescript.h"
#include "modules/gdnative/gdnative.h"
#ifndef NO_THREADS
#include "os/mutex.h"
#endif
struct NativeScriptDesc {
struct Method {
@ -197,6 +201,19 @@ private:
void _unload_stuff();
#ifndef NO_THREADS
Mutex *mutex;
Set<Ref<GDNativeLibrary> > libs_to_init;
Set<NativeScript *> scripts_to_register;
volatile bool has_objects_to_register; // so that we don't lock mutex every frame - it's rarely needed
void defer_init_library(Ref<GDNativeLibrary> lib, NativeScript *script);
#endif
void init_library(const Ref<GDNativeLibrary> &lib);
void register_script(NativeScript *script);
void unregister_script(NativeScript *script);
public:
Map<String, Map<StringName, NativeScriptDesc> > library_classes;
Map<String, Ref<GDNative> > library_gdnatives;
@ -206,6 +223,10 @@ public:
const StringName _init_call_type = "nativescript_init";
const StringName _init_call_name = "godot_nativescript_init";
const StringName _thread_cb_call_type = "godot_nativescript_thread_cb";
const StringName _thread_enter_call_name = "godot_nativescript_thread_enter";
const StringName _thread_exit_call_name = "godot_nativescript_thread_exit";
NativeScriptLanguage();
~NativeScriptLanguage();
@ -215,6 +236,13 @@ public:
void _hacky_api_anchor();
#ifndef NO_THREADS
virtual void thread_enter();
virtual void thread_exit();
virtual void frame();
#endif
virtual String get_name() const;
virtual void init();
virtual String get_type() const;