[Bf-blender-cvs] [06d2ad0] master: BGE: Fix issues with async libload.

Porteries Tristan noreply at git.blender.org
Sun Oct 25 19:19:56 CET 2015


Commit: 06d2ad018564ff0538dad042ebe5670788979171
Author: Porteries Tristan
Date:   Sun Oct 25 19:22:29 2015 +0100
Branches: master
https://developer.blender.org/rB06d2ad018564ff0538dad042ebe5670788979171

BGE: Fix issues with async libload.

This patch fixes:
- the call of LibFree on a unfinished loaded library;
- memory leak created on end of game : the async libraries are loaded but not converted, so not freed with the master scene.

Reviewers: campbellbarton, sybren, youle, hg1, moguri, lordloki

Reviewed By: moguri, lordloki

Differential Revision: https://developer.blender.org/D1571

===================================================================

M	doc/python_api/rst/bge_types/bge.types.KX_LibLoadStatus.rst
M	source/gameengine/Converter/KX_BlenderSceneConverter.cpp
M	source/gameengine/Converter/KX_BlenderSceneConverter.h
M	source/gameengine/Converter/KX_LibLoadStatus.cpp
M	source/gameengine/Converter/KX_LibLoadStatus.h
M	source/gameengine/Ketsji/KX_ISceneConverter.h
M	source/gameengine/Ketsji/KX_KetsjiEngine.cpp

===================================================================

diff --git a/doc/python_api/rst/bge_types/bge.types.KX_LibLoadStatus.rst b/doc/python_api/rst/bge_types/bge.types.KX_LibLoadStatus.rst
index a5b7aaf..a37b4da 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_LibLoadStatus.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_LibLoadStatus.rst
@@ -25,6 +25,12 @@ base class --- :class:`PyObjectPlus`
 
       :type: callable
 
+   .. attribute:: finished
+
+      The current status of the lib load.
+
+      :type: boolean
+
    .. attribute:: progress
 
       The current progress of the lib load as a normalized value from 0.0 to 1.0.
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
index 02c00b2..95d8fe1 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
@@ -138,14 +138,6 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
 	// clears meshes, and hashmaps from blender to gameengine data
 	// delete sumoshapes
 
-	if (m_threadinfo) {
-		BLI_task_pool_work_and_wait(m_threadinfo->m_pool);
-		BLI_task_pool_free(m_threadinfo->m_pool);
-
-		BLI_mutex_end(&m_threadinfo->m_mutex);
-		delete m_threadinfo;
-	}
-
 	int numAdtLists = m_map_blender_to_gameAdtList.size();
 	for (int i = 0; i < numAdtLists; i++) {
 		BL_InterpolatorList *adtList = *m_map_blender_to_gameAdtList.at(i);
@@ -188,6 +180,15 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
 	}
 
 	m_DynamicMaggie.clear();
+
+	if (m_threadinfo) {
+		/* Thread infos like mutex must be freed after FreeBlendFile function.
+		Because it needs to lock the mutex, even if there's no active task when it's
+		in the scene converter destructor. */
+		BLI_task_pool_free(m_threadinfo->m_pool);
+		BLI_mutex_end(&m_threadinfo->m_mutex);
+		delete m_threadinfo;
+	}
 }
 
 void KX_BlenderSceneConverter::SetNewFileName(const STR_String &filename)
@@ -806,6 +807,16 @@ void KX_BlenderSceneConverter::MergeAsyncLoads()
 	BLI_mutex_unlock(&m_threadinfo->m_mutex);
 }
 
+void KX_BlenderSceneConverter::FinalizeAsyncLoads()
+{
+	// Finish all loading libraries.
+	if (m_threadinfo) {
+		BLI_task_pool_work_and_wait(m_threadinfo->m_pool);
+	}
+	// Merge all libraries data in the current scene, to avoid memory leak of unmerged scenes.
+	MergeAsyncLoads();
+}
+
 void KX_BlenderSceneConverter::AddScenesToMergeQueue(KX_LibLoadStatus *status)
 {
 	BLI_mutex_lock(&m_threadinfo->m_mutex);
@@ -1017,7 +1028,19 @@ bool KX_BlenderSceneConverter::FreeBlendFile(Main *maggie)
 
 	if (maggie == NULL)
 		return false;
-	
+
+	// If the given library is currently in loading, we do nothing.
+	if (m_status_map.count(maggie->name)) {
+		BLI_mutex_lock(&m_threadinfo->m_mutex);
+		const bool finished = m_status_map[maggie->name]->IsFinished();
+		BLI_mutex_unlock(&m_threadinfo->m_mutex);
+
+		if (!finished) {
+			printf("Library (%s) is currently being loaded asynchronously, and cannot be freed until this process is done\n", maggie->name);
+			return false;
+		}
+	}
+
 	/* tag all false except the one we remove */
 	for (vector<Main *>::iterator it = m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) {
 		Main *main = *it;
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.h b/source/gameengine/Converter/KX_BlenderSceneConverter.h
index a40188d..40c71a4 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.h
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.h
@@ -184,6 +184,7 @@ public:
 	bool FreeBlendFile(const char *path);
 
 	virtual void MergeAsyncLoads();
+	virtual void FinalizeAsyncLoads();
 	void AddScenesToMergeQueue(class KX_LibLoadStatus *status);
  
 	void PrintStats() {
diff --git a/source/gameengine/Converter/KX_LibLoadStatus.cpp b/source/gameengine/Converter/KX_LibLoadStatus.cpp
index 2a38e06..66fcd99 100644
--- a/source/gameengine/Converter/KX_LibLoadStatus.cpp
+++ b/source/gameengine/Converter/KX_LibLoadStatus.cpp
@@ -36,7 +36,8 @@ KX_LibLoadStatus::KX_LibLoadStatus(class KX_BlenderSceneConverter* kx_converter,
 			m_mergescene(merge_scene),
 			m_data(NULL),
 			m_libname(path),
-			m_progress(0.f)
+			m_progress(0.0f),
+			m_finished(false)
 #ifdef WITH_PYTHON
 			,
 			m_finish_cb(NULL),
@@ -48,6 +49,7 @@ KX_LibLoadStatus::KX_LibLoadStatus(class KX_BlenderSceneConverter* kx_converter,
 
 void KX_LibLoadStatus::Finish()
 {
+	m_finished = true;
 	m_progress = 1.f;
 	m_endtime = PIL_check_seconds_timer();
 
@@ -157,6 +159,7 @@ PyAttributeDef KX_LibLoadStatus::Attributes[] = {
 	KX_PYATTRIBUTE_FLOAT_RO("progress", KX_LibLoadStatus, m_progress),
 	KX_PYATTRIBUTE_STRING_RO("libraryName", KX_LibLoadStatus, m_libname),
 	KX_PYATTRIBUTE_RO_FUNCTION("timeTaken", KX_LibLoadStatus, pyattr_get_timetaken),
+	KX_PYATTRIBUTE_BOOL_RO("finished", KX_LibLoadStatus, m_finished),
 	{ NULL }	//Sentinel
 };
 
diff --git a/source/gameengine/Converter/KX_LibLoadStatus.h b/source/gameengine/Converter/KX_LibLoadStatus.h
index bedf449..fd51bfd 100644
--- a/source/gameengine/Converter/KX_LibLoadStatus.h
+++ b/source/gameengine/Converter/KX_LibLoadStatus.h
@@ -43,6 +43,9 @@ private:
 	double	m_starttime;
 	double	m_endtime;
 
+	// The current status of this libload, used by the scene converter.
+	bool m_finished;
+
 #ifdef WITH_PYTHON
 	PyObject*	m_finish_cb;
 	PyObject*	m_progress_cb;
@@ -68,6 +71,11 @@ public:
 	void SetData(void *data);
 	void *GetData();
 
+	inline bool IsFinished() const
+	{
+		return m_finished;
+	}
+
 	void SetProgress(float progress);
 	float GetProgress();
 	void AddProgress(float progress);
diff --git a/source/gameengine/Ketsji/KX_ISceneConverter.h b/source/gameengine/Ketsji/KX_ISceneConverter.h
index 2e1c16c..1963fc7 100644
--- a/source/gameengine/Ketsji/KX_ISceneConverter.h
+++ b/source/gameengine/Ketsji/KX_ISceneConverter.h
@@ -64,6 +64,7 @@ public:
 
 	// handle any pending merges from asynchronous loads
 	virtual void MergeAsyncLoads()=0;
+	virtual void FinalizeAsyncLoads() = 0;
 
 	virtual void	SetAlwaysUseExpandFraming(bool to_what) = 0;
 
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
index c6e5f73..f42e3e1 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -1273,6 +1273,7 @@ void KX_KetsjiEngine::StopEngine()
 {
 	if (m_bInitialized)
 	{
+		m_sceneconverter->FinalizeAsyncLoads();
 
 		if (m_animation_record)
 		{




More information about the Bf-blender-cvs mailing list