Browse Source

Reworked ResourceManager: collapse ResourceLoader into it and use condition variable to wake up loading thread

Daniele Bartolini 13 years ago
parent
commit
464006bedd
2 changed files with 141 additions and 21 deletions
  1. 100 18
      src/ResourceManager.cpp
  2. 41 3
      src/ResourceManager.h

+ 100 - 18
src/ResourceManager.cpp

@@ -25,24 +25,32 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 
 #include "Types.h"
 #include "Types.h"
 #include "ResourceManager.h"
 #include "ResourceManager.h"
-#include "ResourceLoader.h"
 #include "String.h"
 #include "String.h"
 #include "Hash.h"
 #include "Hash.h"
 #include "Path.h"
 #include "Path.h"
 #include "Log.h"
 #include "Log.h"
 #include <algorithm>
 #include <algorithm>
 
 
+#include "TextResource.h"
 #include "TextureResource.h"
 #include "TextureResource.h"
 
 
 namespace crown
 namespace crown
 {
 {
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-ResourceManager::ResourceManager(ResourceLoader& loader) :
-	m_resource_loader(loader),
+ResourceManager::ResourceManager(ResourceArchive& archive, Allocator& allocator) :
+	m_resource_archive(archive),
+	m_resource_allocator(allocator),
 	m_resources(m_allocator),
 	m_resources(m_allocator),
-	m_loading_queue(m_allocator)
+	m_loading_queue(m_allocator),
+	m_loaded_queue(m_allocator),
+	m_thread(ResourceManager::background_thread, (void*)this, "resource-loader-thread")
 {
 {
+	// FIXME hardcoded seed
+	m_config_hash = hash::murmur2_32("config", string::strlen("config"), 0);
+	m_texture_hash = hash::murmur2_32("tga", string::strlen("tga"), 0);
+	m_mesh_hash = hash::murmur2_32("mesh", string::strlen("mesh"), 0);
+	m_txt_hash = hash::murmur2_32("txt", 3, 0);
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -89,7 +97,10 @@ ResourceId ResourceManager::load(uint32_t name, uint32_t type)
 		entry.resource = NULL;
 		entry.resource = NULL;
 
 
 		m_resources.push_back(entry);
 		m_resources.push_back(entry);
+
+		m_loading_mutex.lock();
 		m_loading_queue.push_back(id);
 		m_loading_queue.push_back(id);
+		m_loading_mutex.unlock();
 
 
 		return id;
 		return id;
 	}
 	}
@@ -111,7 +122,7 @@ void ResourceManager::unload(ResourceId name)
 	
 	
 	if (entry.references == 0 && entry.state == RS_LOADED)
 	if (entry.references == 0 && entry.state == RS_LOADED)
 	{
 	{
-		m_resource_loader.unload(name, entry.resource);
+		//m_resource_loader.unload(name, entry.resource);
 
 
 		entry.state = RS_UNLOADED;
 		entry.state = RS_UNLOADED;
 		entry.resource = NULL;
 		entry.resource = NULL;
@@ -169,35 +180,99 @@ uint32_t ResourceManager::references(ResourceId name) const
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void ResourceManager::flush_load_queue()
 void ResourceManager::flush_load_queue()
 {
 {
-	while (m_loading_queue.size() > 0)
+	m_loading_mutex.lock();
+
+	if (m_loading_queue.size() > 0)
 	{
 	{
-		ResourceId resource = m_loading_queue.front();
+		m_loading_requests.signal();
+	}
+	
+	m_loading_mutex.unlock();
+}
+
+//-----------------------------------------------------------------------------
+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();
+		m_loaded_queue.pop_front();
+
+		online(lr.resource, lr.data);
+	}
+
+	m_loaded_mutex.unlock();
+}
 
 
-		m_resource_loader.load(resource);
+//-----------------------------------------------------------------------------
+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);
 
 
+		ResourceId resource = m_loading_queue.front();
 		m_loading_queue.pop_front();
 		m_loading_queue.pop_front();
 
 
-		m_resources[resource.index].state = RS_LOADING;
+		m_loading_mutex.unlock();
+
+		void* data = load_by_type(resource);
+
+		LoadedResource lr;
+		lr.resource = resource;
+		lr.data = data;
+
+		m_loaded_mutex.lock();
+
+		m_loaded_queue.push_back(lr);
+
+		m_loaded_mutex.unlock();
 	}
 	}
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-void ResourceManager::bring_loaded_online()
+void* ResourceManager::load_by_type(ResourceId name) const
 {
 {
-	m_resource_loader.m_loaded_mutex.lock();
+	if (name.type == m_config_hash)
+	{
+		return NULL;
+	}
+	else if (name.type == m_texture_hash)
+	{
+		return TextureResource::load(m_resource_allocator, &m_resource_archive, name);
+	}
+	else if (name.type == m_txt_hash)
+	{
+		return TextResource::load(m_resource_allocator, &m_resource_archive, name);
+	}
 
 
-	Queue<LoadedResource>& loaded = m_resource_loader.m_loaded_resources;
+	return NULL;
+}
 
 
-	while (loaded.size() > 0)
+//-----------------------------------------------------------------------------
+void ResourceManager::unload_by_type(ResourceId name, void* resource) const
+{
+	if (name.type == m_config_hash)
 	{
 	{
-		LoadedResource lr = loaded.front();
+		return;
+	}
 
 
-		online(lr.resource, lr.data);
+	if (name.type == m_texture_hash)
+	{
+		TextureResource::unload(m_resource_allocator, (TextureResource*)resource);
+	}
 
 
-		loaded.pop_front();
+	if (name.type == m_txt_hash)
+	{
+		TextResource::unload(m_resource_allocator, (TextResource*)resource);
 	}
 	}
 
 
-	m_resource_loader.m_loaded_mutex.unlock();
+	return;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -215,5 +290,12 @@ void ResourceManager::online(ResourceId name, void* resource)
 	entry.state = RS_LOADED;
 	entry.state = RS_LOADED;
 }
 }
 
 
-} // namespace crown
+//-----------------------------------------------------------------------------
+void* ResourceManager::background_thread(void* thiz)
+{
+	ResourceManager* mgr = (ResourceManager*)thiz;
 
 
+	mgr->background_load();
+}
+
+} // namespace crown

+ 41 - 3
src/ResourceManager.h

@@ -30,6 +30,9 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Queue.h"
 #include "Queue.h"
 #include "Resource.h"
 #include "Resource.h"
 #include "MallocAllocator.h"
 #include "MallocAllocator.h"
+#include "Thread.h"
+#include "Mutex.h"
+#include "Cond.h"
 
 
 namespace crown
 namespace crown
 {
 {
@@ -54,14 +57,20 @@ struct ResourceEntry
 					}
 					}
 };
 };
 
 
-class ResourceLoader;
+struct LoadedResource
+{
+	ResourceId	resource;
+	void*		data;
+};
+
+class ResourceArchive;
 
 
 /// Resource manager.
 /// Resource manager.
 class ResourceManager
 class ResourceManager
 {
 {
 public:
 public:
 
 
-							ResourceManager(ResourceLoader& loader);
+							ResourceManager(ResourceArchive& archive, Allocator& allocator);
 							~ResourceManager();
 							~ResourceManager();
 
 
 	/// Loads the resource by @name and returns its ResourceId.
 	/// Loads the resource by @name and returns its ResourceId.
@@ -110,16 +119,45 @@ public:
 
 
 private:
 private:
 
 
+	void					background_load();
+
+	void*					load_by_type(ResourceId name) const;
+	void					unload_by_type(ResourceId name, void* resource) const;
 	void					online(ResourceId name, void* resource);
 	void					online(ResourceId name, void* resource);
 
 
 private:
 private:
 
 
-	ResourceLoader&			m_resource_loader;
+	static void*			background_thread(void* thiz);
+
+private:
+
+	// Archive whether to look for resources
+	ResourceArchive&		m_resource_archive;
+	// Used to strore resource memory
+	Allocator&				m_resource_allocator;
 
 
 	MallocAllocator			m_allocator;
 	MallocAllocator			m_allocator;
+	// The master lookup table
 	List<ResourceEntry>		m_resources;
 	List<ResourceEntry>		m_resources;
 
 
+	// Resources waiting for loading
 	Queue<ResourceId>		m_loading_queue;
 	Queue<ResourceId>		m_loading_queue;
+	// Resources already loaded, ready to bring online
+	Queue<LoadedResource>	m_loaded_queue;
+
+	// Background loading thread
+	Thread					m_thread;
+	Mutex					m_loading_mutex;
+	Cond 					m_loading_requests;
+	Mutex					m_loaded_mutex;
+
+private:
+
+	// Hashes of resource types (FIXME)
+	uint32_t			m_config_hash;
+	uint32_t			m_texture_hash;
+	uint32_t			m_mesh_hash;
+	uint32_t			m_txt_hash;
 };
 };
 
 
 } // namespace crown
 } // namespace crown