2
0
Эх сурвалжийг харах

GDScriptCache: Clear abandoned parser refs

rune-scape 1 жил өмнө
parent
commit
86b23d0420

+ 32 - 1
modules/gdscript/gdscript_cache.cpp

@@ -135,7 +135,9 @@ void GDScriptParserRef::clear() {
 
 
 GDScriptParserRef::~GDScriptParserRef() {
 GDScriptParserRef::~GDScriptParserRef() {
 	clear();
 	clear();
-	GDScriptCache::remove_parser(path);
+	if (!abandoned) {
+		GDScriptCache::remove_parser(path);
+	}
 }
 }
 
 
 GDScriptCache *GDScriptCache::singleton = nullptr;
 GDScriptCache *GDScriptCache::singleton = nullptr;
@@ -183,6 +185,17 @@ void GDScriptCache::remove_script(const String &p_path) {
 		return;
 		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)) {
 	if (singleton->parser_map.has(p_path)) {
 		singleton->parser_map[p_path]->clear();
 		singleton->parser_map[p_path]->clear();
 	}
 	}
@@ -229,6 +242,13 @@ bool GDScriptCache::has_parser(const String &p_path) {
 
 
 void GDScriptCache::remove_parser(const String &p_path) {
 void GDScriptCache::remove_parser(const String &p_path) {
 	MutexLock lock(singleton->mutex);
 	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.
 	// 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);
 	singleton->parser_map.erase(p_path);
 
 
@@ -432,6 +452,17 @@ void GDScriptCache::clear() {
 
 
 	singleton->parser_inverse_dependencies.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;
 	RBSet<Ref<GDScriptParserRef>> parser_map_refs;
 	for (KeyValue<String, GDScriptParserRef *> &E : singleton->parser_map) {
 	for (KeyValue<String, GDScriptParserRef *> &E : singleton->parser_map) {
 		parser_map_refs.insert(E.value);
 		parser_map_refs.insert(E.value);

+ 2 - 0
modules/gdscript/gdscript_cache.h

@@ -59,6 +59,7 @@ private:
 	String path;
 	String path;
 	uint32_t source_hash = 0;
 	uint32_t source_hash = 0;
 	bool clearing = false;
 	bool clearing = false;
+	bool abandoned = false;
 
 
 	friend class GDScriptCache;
 	friend class GDScriptCache;
 	friend class GDScript;
 	friend class GDScript;
@@ -79,6 +80,7 @@ public:
 class GDScriptCache {
 class GDScriptCache {
 	// String key is full path.
 	// String key is full path.
 	HashMap<String, GDScriptParserRef *> parser_map;
 	HashMap<String, GDScriptParserRef *> parser_map;
+	HashMap<String, Vector<ObjectID>> abandoned_parser_map;
 	HashMap<String, Ref<GDScript>> shallow_gdscript_cache;
 	HashMap<String, Ref<GDScript>> shallow_gdscript_cache;
 	HashMap<String, Ref<GDScript>> full_gdscript_cache;
 	HashMap<String, Ref<GDScript>> full_gdscript_cache;
 	HashMap<String, Ref<GDScript>> static_gdscript_cache;
 	HashMap<String, Ref<GDScript>> static_gdscript_cache;