GDExtension API to fetch singletons
There is an FFI function to fetch a singleton:
typedef GDExtensionObjectPtr (*GDExtensionInterfaceGlobalGetSingleton)(GDExtensionConstStringNamePtr p_name);
Notably, this returns null if the singleton is not yet initialized (before a certain init stage).
What we need to test is whether it also returns null after a certain deinit stage.
Caching
Fetching these pointers via FFI + Godot lookup every time a singleton API is called shouldn't be necessary. Thoughts:
- One way is to cache by singleton name / class ID / type ID, in a Rust-side global
HashMap.
- As singletons tend to be accessed from multiple threads, we'd need a locking strategy.
- We can optimize this, so that during "fully initialized" (after
MainLoop init), we assume the hashmap doesn't change. It would need an AtomicBool (for the "fully initialized" flag accessed from different threads), after that a raw hashmap access. Or a Mutex if that's faster.
- We'd also need to see what key to use.
GodotClass::class_id() retrieves the ID from a static OnceLock<ClassId> which should be pretty fast. It's a bit a shame that there's no good compile time solution (const_type_id is nightly, and even crates emulating it will need the hash computation).
- Blazingly fast would be to do it directly via
trait, not needing hashmaps at all. Since all singletons are statically known via Singleton trait, we can override the singleton() method (or add another one) to store a static OnceLock<Something<Gd<T>>>. We'd somehow need to get the thread safety sorted, and make sure to have an extra check whether the singletons is initialized (already + still).
- I would not cache any dynamic singletons registered via
Engine::register_singleton, or registered in GDScript.
GDExtension API to fetch singletons
There is an FFI function to fetch a singleton:
Notably, this returns null if the singleton is not yet initialized (before a certain init stage).
What we need to test is whether it also returns null after a certain deinit stage.
Caching
Fetching these pointers via FFI + Godot lookup every time a singleton API is called shouldn't be necessary. Thoughts:
HashMap.MainLoopinit), we assume the hashmap doesn't change. It would need anAtomicBool(for the "fully initialized" flag accessed from different threads), after that a raw hashmap access. Or aMutexif that's faster.GodotClass::class_id()retrieves the ID from astatic OnceLock<ClassId>which should be pretty fast. It's a bit a shame that there's no good compile time solution (const_type_idis nightly, and even crates emulating it will need the hash computation).trait, not needing hashmaps at all. Since all singletons are statically known viaSingletontrait, we can override thesingleton()method (or add another one) to store astatic OnceLock<Something<Gd<T>>>. We'd somehow need to get the thread safety sorted, and make sure to have an extra check whether the singletons is initialized (already + still).Engine::register_singleton, or registered in GDScript.