diff options
author | Lyuma <xn.lyuma@gmail.com> | 2020-11-01 00:44:15 -0700 |
---|---|---|
committer | Lyuma <xn.lyuma@gmail.com> | 2020-11-01 03:40:06 -0800 |
commit | 37b6a36cc4b5a4dec6c2c2996864ca06c7f37672 (patch) | |
tree | bb68a15a143111446fd9f546a4158ee129d9ad4e | |
parent | 7bc74b0fc802368a91b6a59e4a5e0989c0f51d06 (diff) |
Avoid reentrant OBJTYPE_RLOCK in ClassDB
Fixes #43020 when a thread uses ClassDB while main thread calls is_parent_class().
-rw-r--r-- | core/class_db.cpp | 26 | ||||
-rw-r--r-- | core/class_db.h | 5 |
2 files changed, 22 insertions, 9 deletions
diff --git a/core/class_db.cpp b/core/class_db.cpp index ad85cd0d62..81bc901561 100644 --- a/core/class_db.cpp +++ b/core/class_db.cpp @@ -242,21 +242,25 @@ HashMap<StringName, ClassDB::ClassInfo> ClassDB::classes; HashMap<StringName, StringName> ClassDB::resource_base_extensions; HashMap<StringName, StringName> ClassDB::compat_classes; -bool ClassDB::is_parent_class(const StringName &p_class, const StringName &p_inherits) { - OBJTYPE_RLOCK; - +bool ClassDB::_is_parent_class(const StringName &p_class, const StringName &p_inherits) { StringName inherits = p_class; while (inherits.operator String().length()) { if (inherits == p_inherits) { return true; } - inherits = get_parent_class(inherits); + inherits = _get_parent_class(inherits); } return false; } +bool ClassDB::is_parent_class(const StringName &p_class, const StringName &p_inherits) { + OBJTYPE_RLOCK; + + return _is_parent_class(p_class, p_inherits); +} + void ClassDB::get_class_list(List<StringName> *p_classes) { OBJTYPE_RLOCK; @@ -275,7 +279,7 @@ void ClassDB::get_inheriters_from_class(const StringName &p_class, List<StringNa const StringName *k = nullptr; while ((k = classes.next(k))) { - if (*k != p_class && is_parent_class(*k, p_class)) { + if (*k != p_class && _is_parent_class(*k, p_class)) { p_classes->push_back(*k); } } @@ -287,7 +291,7 @@ void ClassDB::get_direct_inheriters_from_class(const StringName &p_class, List<S const StringName *k = nullptr; while ((k = classes.next(k))) { - if (*k != p_class && get_parent_class(*k) == p_class) { + if (*k != p_class && _get_parent_class(*k) == p_class) { p_classes->push_back(*k); } } @@ -315,14 +319,18 @@ StringName ClassDB::get_compatibility_remapped_class(const StringName &p_class) return p_class; } -StringName ClassDB::get_parent_class(const StringName &p_class) { - OBJTYPE_RLOCK; - +StringName ClassDB::_get_parent_class(const StringName &p_class) { ClassInfo *ti = classes.getptr(p_class); ERR_FAIL_COND_V_MSG(!ti, StringName(), "Cannot get class '" + String(p_class) + "'."); return ti->inherits; } +StringName ClassDB::get_parent_class(const StringName &p_class) { + OBJTYPE_RLOCK; + + return _get_parent_class(p_class); +} + ClassDB::APIType ClassDB::get_api_type(const StringName &p_class) { OBJTYPE_RLOCK; diff --git a/core/class_db.h b/core/class_db.h index 4734b06c7a..22072066d9 100644 --- a/core/class_db.h +++ b/core/class_db.h @@ -164,6 +164,11 @@ public: static HashMap<StringName, HashMap<StringName, Variant>> default_values; static Set<StringName> default_values_cached; +private: + // Non-locking variants of get_parent_class and is_parent_class. + static StringName _get_parent_class(const StringName &p_class); + static bool _is_parent_class(const StringName &p_class, const StringName &p_inherits); + public: // DO NOT USE THIS!!!!!! NEEDS TO BE PUBLIC BUT DO NOT USE NO MATTER WHAT!!! template <class T> |