Просмотр исходного кода

Add flush() method to ResourceManager to force all request to complete before proceeding. Needs extensive test.

Daniele Bartolini 12 лет назад
Родитель
Сommit
e70f595ba6
2 измененных файлов с 69 добавлено и 11 удалено
  1. 50 7
      src/ResourceManager.cpp
  2. 19 4
      src/ResourceManager.h

+ 50 - 7
src/ResourceManager.cpp

@@ -182,7 +182,44 @@ uint32_t ResourceManager::references(ResourceId name) const
 }
 
 //-----------------------------------------------------------------------------
-void ResourceManager::flush_load_queue()
+uint32_t ResourceManager::remaining() const
+{
+	uint32_t count = 0;
+
+	m_loading_mutex.lock();
+
+	count = m_loading_queue.size();
+
+	m_loading_mutex.unlock();
+
+	return count;
+}
+
+//-----------------------------------------------------------------------------
+void ResourceManager::flush()
+{
+	check_load_queue();
+
+	while (true)
+	{
+		// Wait for all the resources to be loaded
+		// by the background thread
+		m_loading_mutex.lock();
+		while (m_loading_queue.size() > 0)
+		{
+			m_all_loaded.wait(m_loading_mutex);
+		}
+		m_loading_mutex.unlock();
+
+		// When all loaded, bring them online
+		bring_loaded_online();
+
+		return;
+	}
+}
+
+//-----------------------------------------------------------------------------
+void ResourceManager::check_load_queue()
 {
 	m_loading_mutex.lock();
 
@@ -190,7 +227,7 @@ void ResourceManager::flush_load_queue()
 	{
 		m_loading_requests.signal();
 	}
-	
+
 	m_loading_mutex.unlock();
 }
 
@@ -199,7 +236,6 @@ void ResourceManager::bring_loaded_online()
 {
 	m_loaded_mutex.lock();
 
-	// Update master table and bring online
 	while (m_loaded_queue.size() > 0)
 	{
 		LoadedResource lr = m_loaded_queue.front();
@@ -251,11 +287,13 @@ ResourceId ResourceManager::load(uint32_t name, uint32_t type)
 //-----------------------------------------------------------------------------
 void ResourceManager::background_load()
 {
-	// FIXME: Maybe epic crash because of concurrent access to the same allocator?
 	while (true)
 	{
 		m_loading_mutex.lock();
-		m_loading_requests.wait(m_loading_mutex);
+		while (m_loading_queue.size() == 0)
+		{
+			m_loading_requests.wait(m_loading_mutex);
+		}
 
 		ResourceId resource = m_loading_queue.front();
 		m_loading_queue.pop_front();
@@ -269,10 +307,15 @@ void ResourceManager::background_load()
 		lr.data = data;
 
 		m_loaded_mutex.lock();
-
 		m_loaded_queue.push_back(lr);
-
 		m_loaded_mutex.unlock();
+
+		m_loading_mutex.lock();
+		if (m_loading_queue.size() == 0)
+		{
+			m_all_loaded.signal();
+		}
+		m_loading_mutex.unlock();
 	}
 }
 

+ 19 - 4
src/ResourceManager.h

@@ -110,14 +110,24 @@ public:
 	/// you can use the data associated with it).
 	bool					is_loaded(ResourceId name) const;
 
-	// Returns the number of references to the @resource
+	/// Returns the number of references to the @resource
 	uint32_t				references(ResourceId name) const;
 
-	void					flush_load_queue();
-	void					bring_loaded_online();
+	/// Returns the number of resources still waiting to load.
+	uint32_t				remaining() const;
+
+	/// Forces all the loading requests to complete before preceeding.
+	void					flush();
 
 private:
 
+	// Checks the load queue and signal the backgroud about pending
+	// requests. It is normally called only by the Device.
+	void					check_load_queue();
+	// Calls online() on loaded resources. Must be called only
+	// in the main thread and generally only by Device.
+	void					bring_loaded_online();
+
 	// Loads the resource by name and type and returns its ResourceId.
 	ResourceId				load(uint32_t name, uint32_t type);
 
@@ -149,8 +159,11 @@ private:
 
 	// Background loading thread
 	Thread					m_thread;
-	Mutex					m_loading_mutex;
+
+	mutable Mutex			m_loading_mutex;
 	Cond 					m_loading_requests;
+	Cond 					m_all_loaded;
+
 	Mutex					m_loaded_mutex;
 	mutable Mutex			m_resources_mutex;
 
@@ -161,6 +174,8 @@ private:
 	uint32_t			m_mesh_hash;
 	uint32_t			m_txt_hash;
 	uint32_t			m_script_hash;
+
+	friend class		Device;
 };
 
 } // namespace crown