Skip to content

Commit

Permalink
GDScriptCache: Clear abandoned parser refs
Browse files Browse the repository at this point in the history
  • Loading branch information
rune-scape committed Jul 23, 2024
1 parent 8e36f98 commit 86b23d0
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 1 deletion.
33 changes: 32 additions & 1 deletion modules/gdscript/gdscript_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,9 @@ void GDScriptParserRef::clear() {

GDScriptParserRef::~GDScriptParserRef() {
clear();
GDScriptCache::remove_parser(path);
if (!abandoned) {
GDScriptCache::remove_parser(path);
}
}

GDScriptCache *GDScriptCache::singleton = nullptr;
Expand Down Expand Up @@ -183,6 +185,17 @@ void GDScriptCache::remove_script(const String &p_path) {
return;
}

if (HashMap<String, Vector<ObjectID>>::Iterator E = singleton->abandoned_parser_map.find(p_path)) {
for (ObjectID parser_ref_id : E->value) {
Ref<GDScriptParserRef> parser_ref{ ObjectDB::get_instance(parser_ref_id) };
if (parser_ref.is_valid()) {
parser_ref->clear();
}
}
}

singleton->abandoned_parser_map.erase(p_path);

if (singleton->parser_map.has(p_path)) {
singleton->parser_map[p_path]->clear();
}
Expand Down Expand Up @@ -229,6 +242,13 @@ bool GDScriptCache::has_parser(const String &p_path) {

void GDScriptCache::remove_parser(const String &p_path) {
MutexLock lock(singleton->mutex);

if (singleton->parser_map.has(p_path)) {
GDScriptParserRef *parser_ref = singleton->parser_map[p_path];
parser_ref->abandoned = true;
singleton->abandoned_parser_map[p_path].push_back(parser_ref->get_instance_id());
}

// Can't clear the parser because some other parser might be currently using it in the chain of calls.
singleton->parser_map.erase(p_path);

Expand Down Expand Up @@ -432,6 +452,17 @@ void GDScriptCache::clear() {

singleton->parser_inverse_dependencies.clear();

for (const KeyValue<String, Vector<ObjectID>> &KV : singleton->abandoned_parser_map) {
for (ObjectID parser_ref_id : KV.value) {
Ref<GDScriptParserRef> parser_ref{ ObjectDB::get_instance(parser_ref_id) };
if (parser_ref.is_valid()) {
parser_ref->clear();
}
}
}

singleton->abandoned_parser_map.clear();

RBSet<Ref<GDScriptParserRef>> parser_map_refs;
for (KeyValue<String, GDScriptParserRef *> &E : singleton->parser_map) {
parser_map_refs.insert(E.value);
Expand Down
2 changes: 2 additions & 0 deletions modules/gdscript/gdscript_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class GDScriptParserRef : public RefCounted {
String path;
uint32_t source_hash = 0;
bool clearing = false;
bool abandoned = false;

friend class GDScriptCache;
friend class GDScript;
Expand All @@ -79,6 +80,7 @@ class GDScriptParserRef : public RefCounted {
class GDScriptCache {
// String key is full path.
HashMap<String, GDScriptParserRef *> parser_map;
HashMap<String, Vector<ObjectID>> abandoned_parser_map;
HashMap<String, Ref<GDScript>> shallow_gdscript_cache;
HashMap<String, Ref<GDScript>> full_gdscript_cache;
HashMap<String, Ref<GDScript>> static_gdscript_cache;
Expand Down

0 comments on commit 86b23d0

Please sign in to comment.