فهرست منبع

Refactor ResourceManager to adapt to latest Thread implementation

Daniele Bartolini 12 سال پیش
والد
کامیت
7d8137e008

+ 1 - 0
engine/Android.mk

@@ -89,6 +89,7 @@ LOCAL_SRC_FILES :=\
 	resource/FontResource.cpp\
 	resource/MaterialResource.cpp\
 	resource/PixelShaderResource.cpp\
+	resource/ResourceLoader.cpp\
 	resource/ResourceManager.cpp\
 	resource/TextResource.cpp\
 	resource/TextureResource.cpp\

+ 17 - 0
engine/CMakeLists.txt

@@ -54,6 +54,7 @@ set (CROWN_INCLUDES
 	${CMAKE_SOURCE_DIR}/engine/input
 	${CMAKE_SOURCE_DIR}/engine/renderers
 	${CMAKE_SOURCE_DIR}/engine/resource
+	${CMAKE_SOURCE_DIR}/engine/rpc
 	${CMAKE_SOURCE_DIR}/engine/network
 	${CMAKE_SOURCE_DIR}/engine/lua
 )
@@ -270,6 +271,7 @@ set (RENDERERS_HEADERS
 
 set (RESOURCE_SRC
 	resource/MaterialResource.cpp
+	resource/ResourceLoader.cpp
 	resource/ResourceManager.cpp
 	resource/TextureResource.cpp
 	resource/MeshResource.cpp
@@ -282,6 +284,7 @@ set (RESOURCE_SRC
 set (RESOURCE_HEADERS
 	resource/MaterialResource.h
 	resource/Resource.h
+	resource/ResourceLoader.h
 	resource/ResourceManager.h
 	resource/Bundle.h
 	resource/TextureResource.h
@@ -292,6 +295,16 @@ set (RESOURCE_HEADERS
 	resource/FileBundle.h
 )
 
+set (RPC_SRC
+#	rpc/RPCServer.cpp
+#	rpc/RPCConnection.cpp
+)
+
+set (RPC_HEADERS
+#	rpc/RPCServer.h
+#	rpc/RPCConnection.h
+)
+
 set (OS_SRC
 	os/OS.cpp
 )
@@ -464,6 +477,8 @@ set (CROWN_SOURCES
 
 	${RESOURCE_SRC}
 
+	${RPC_SRC}
+
 #	${NETWORK_SRC}
 
 	${OS_SRC}
@@ -489,6 +504,8 @@ set (CROWN_HEADERS
 
 	${RESOURCE_HEADERS}
 
+	${RPC_HEADERS}
+
 #	${NETWORK_HEADERS}
 
 	${OS_HEADERS}

+ 1 - 0
engine/Crown.h

@@ -135,6 +135,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Bundle.h"
 #include "ArchiveBundle.h"
 #include "FileBundle.h"
+#include "ResourceLoader.h"
 #include "ResourceManager.h"
 #include "TextureResource.h"
 #include "MeshResource.h"

+ 132 - 0
engine/resource/ResourceLoader.cpp

@@ -0,0 +1,132 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "ResourceLoader.h"
+#include "TextureResource.h"
+#include "MeshResource.h"
+#include "SoundResource.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+ResourceLoader::ResourceLoader(Bundle& bundle) :
+	Thread("resource-loader"),
+	m_bundle(bundle),
+	m_load_queue(m_allocator),
+	m_done_queue(m_allocator)
+{
+}
+
+//-----------------------------------------------------------------------------
+void ResourceLoader::load(ResourceId resource)
+{
+	m_load_mutex.lock();
+	m_load_queue.push_back(resource);
+	m_load_requests.signal();
+	m_load_mutex.unlock();
+}
+
+//-----------------------------------------------------------------------------
+void ResourceLoader::unload(ResourceId resource, void* data)
+{
+	unload_by_type(resource, data);
+}
+
+//-----------------------------------------------------------------------------
+uint32_t ResourceLoader::remaining() const
+{
+	return m_load_queue.size();
+}
+
+//-----------------------------------------------------------------------------
+uint32_t ResourceLoader::num_loaded() const
+{
+	return m_done_queue.size();
+}
+
+//-----------------------------------------------------------------------------
+void ResourceLoader::get_loaded(List<LoadedResource>& l)
+{
+	m_done_mutex.lock();
+	for (uint32_t i = 0; i < m_done_queue.size(); i++)
+	{
+		l.push_back(m_done_queue[i]);
+	}
+
+	m_done_queue.clear();
+	m_done_mutex.unlock();
+}
+
+//-----------------------------------------------------------------------------
+int32_t ResourceLoader::run()
+{
+	while (!is_terminating())
+	{
+		m_load_mutex.lock();
+		while (m_load_queue.size() == 0)
+		{
+			m_load_requests.wait(m_load_mutex);
+		}
+
+		ResourceId resource = m_load_queue.front();
+		m_load_queue.pop_front();
+		m_load_mutex.unlock();
+
+		void* data = load_by_type(resource);
+
+		m_done_mutex.lock();
+		m_done_queue.push_back(LoadedResource(resource, data));
+		m_done_mutex.unlock();
+	}
+
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+void* ResourceLoader::load_by_type(ResourceId name)
+{
+	switch (name.type)
+	{
+		case TEXTURE_TYPE: return TextureResource::load(m_resource_allocator, m_bundle, name);
+		case MESH_TYPE: return MeshResource::load(m_resource_allocator, m_bundle, name);
+		case SOUND_TYPE: return SoundResource::load(m_resource_allocator, m_bundle, name);
+		default: return NULL;
+	}
+}
+
+//-----------------------------------------------------------------------------
+void ResourceLoader::unload_by_type(ResourceId name, void* data)
+{
+	switch (name.type)
+	{
+		case TEXTURE_TYPE: return TextureResource::unload(m_resource_allocator, data);
+		case MESH_TYPE: return MeshResource::unload(m_resource_allocator, data);
+		case SOUND_TYPE: return SoundResource::unload(m_resource_allocator, data);
+	}
+}
+
+} // namespace crown

+ 98 - 0
engine/resource/ResourceLoader.h

@@ -0,0 +1,98 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#pragma once
+
+#include "Types.h"
+#include "Thread.h"
+#include "Resource.h"
+#include "HeapAllocator.h"
+#include "Queue.h"
+#include "List.h"
+#include "Mutex.h"
+#include "Cond.h"
+
+namespace crown
+{
+
+struct LoadedResource
+{
+	LoadedResource(ResourceId r, void* d) : resource(r), data(d) {}
+
+	ResourceId	resource;
+	void*		data;
+};
+
+class Bundle;
+
+/// Loads resources in a background thread.
+class ResourceLoader : public Thread
+{
+public:
+
+	/// Reads the resource data from the given @a bundle.
+				ResourceLoader(Bundle& bundle);
+
+	/// Loads the @a resource in a background thread.
+	void		load(ResourceId resource);
+
+	/// Unloads the given @a resource @a data
+	void		unload(ResourceId resource, void* data);
+
+	/// Returns the number of resources still in the loading queue.
+	uint32_t	remaining() const;
+
+	/// Returns the number of resources already loaded.
+	uint32_t	num_loaded() const;
+
+	/// Returns a list of the last loaded resources.
+	void		get_loaded(List<LoadedResource>& l);
+
+	// Loads resources in the loading queue.
+	int32_t		run();
+
+private:
+
+	void*		load_by_type(ResourceId name);
+	void		unload_by_type(ResourceId name, void* data);
+
+private:
+
+	// Used to strore resource memory
+	HeapAllocator			m_allocator;
+	HeapAllocator			m_resource_allocator;
+
+	// Whether to look for resources
+	Bundle&					m_bundle;
+
+	Queue<ResourceId>		m_load_queue;
+	List<LoadedResource>	m_done_queue;
+	Mutex					m_load_mutex;
+	Mutex					m_done_mutex;
+	Cond					m_load_requests;
+};
+
+} // namespace crown

+ 25 - 193
engine/resource/ResourceManager.cpp

@@ -40,19 +40,17 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "TextureResource.h"
 #include "MeshResource.h"
 #include "SoundResource.h"
+#include "TempAllocator.h"
+#include "List.h"
 
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
 ResourceManager::ResourceManager(Bundle& bundle) :
-	m_resource_bundle(bundle),
-	m_resources(m_allocator),
-	m_loading_queue(m_allocator),
-	m_loaded_queue(m_allocator),
+	m_loader(bundle),
 	m_seed(0),
-	m_background_thread_should_run(true),
-	m_thread(ResourceManager::background_thread, (void*)this, "resource-loader-thread")
+	m_resources(m_allocator)
 {
 	DiskFile* seed_file = device()->filesystem()->open("seed.ini", FOM_READ);
 	TextReader reader(*seed_file);
@@ -63,12 +61,14 @@ ResourceManager::ResourceManager(Bundle& bundle) :
 	device()->filesystem()->close(seed_file);
 
 	sscanf(tmp_buf, "%u", &m_seed);
+
+	m_loader.start();
 }
 
 //-----------------------------------------------------------------------------
 ResourceManager::~ResourceManager()
 {
-	m_background_thread_should_run = false;
+	m_loader.stop();
 }
 
 //-----------------------------------------------------------------------------
@@ -90,8 +90,6 @@ ResourceId ResourceManager::load(const char* name)
 void ResourceManager::unload(ResourceId name)
 {
 	CE_ASSERT(has(name), "Resource not loaded: %.8X%.8X", name.name, name.type);
-	
-	m_resources_mutex.lock();
 
 	ResourceEntry& entry = m_resources[name.index];
 	
@@ -99,69 +97,30 @@ void ResourceManager::unload(ResourceId name)
 	
 	if (entry.references == 0 && entry.state == RS_LOADED)
 	{
-		unload_by_type(name, entry.resource);
+		m_loader.unload(name, entry.resource);
 
 		entry.state = RS_UNLOADED;
 		entry.resource = NULL;
-
-
 	}
-
-	m_resources_mutex.unlock();
-}
-
-//-----------------------------------------------------------------------------
-void ResourceManager::reload(ResourceId name)
-{
-	CE_ASSERT(has(name), "Resource not loaded: %.8X%.8X", name.name, name.type);
-	
-	m_resources_mutex.lock();
-
-	ResourceEntry& entry = m_resources[name.index];
-	
-	if (entry.state == RS_LOADED)
-	{
-		unload_by_type(name, entry.resource);
-
-		entry.state = RS_UNLOADED;
-		entry.resource = NULL;
-
-		entry.resource = load_by_type(name);
-		entry.state = RS_LOADED;
-	}
-
-	m_resources_mutex.unlock();
 }
 
 //-----------------------------------------------------------------------------
 bool ResourceManager::has(ResourceId name) const
 {
-	bool has_resource = false;
-
-	m_resources_mutex.lock();
-
 	if (m_resources.size() > name.index)
 	{
-		 has_resource = (m_resources[name.index].id.name == name.name);
+		 return (m_resources[name.index].id.name == name.name);
 	}
 
-	m_resources_mutex.unlock();
-	
-	return has_resource;
+	return false;
 }
 
 //-----------------------------------------------------------------------------
 const void* ResourceManager::data(ResourceId name) const
 {
 	CE_ASSERT(has(name), "Resource not loaded: %.8X%.8X", name.name, name.type);
-	
-	m_resources_mutex.lock();
 
-	void* resource = m_resources[name.index].resource;
-
-	m_resources_mutex.unlock();
-
-	return resource;
+	return m_resources[name.index].resource;
 }
 
 //-----------------------------------------------------------------------------
@@ -169,13 +128,7 @@ bool ResourceManager::is_loaded(ResourceId name) const
 {
 	CE_ASSERT(has(name), "Resource not loaded: %.8X%.8X", name.name, name.type);
 
-	m_resources_mutex.lock();
-
-	bool loaded = m_resources[name.index].state == RS_LOADED;
-
-	m_resources_mutex.unlock();
-
-	return loaded;
+	return m_resources[name.index].state == RS_LOADED;
 }
 
 //-----------------------------------------------------------------------------
@@ -183,50 +136,15 @@ uint32_t ResourceManager::references(ResourceId name) const
 {
 	CE_ASSERT(has(name), "Resource not loaded: %.8X%.8X", name.name, name.type);
 
-	m_resources_mutex.lock();
-
-	bool loaded = m_resources[name.index].references;
-
-	m_resources_mutex.unlock();
-
-	return loaded;
-}
-
-//-----------------------------------------------------------------------------
-uint32_t ResourceManager::remaining() const
-{
-	uint32_t count = 0;
-
-	m_loading_mutex.lock();
-
-	count = m_loading_queue.size();
-
-	m_loading_mutex.unlock();
-
-	return count;
+	return m_resources[name.index].references;
 }
 
 //-----------------------------------------------------------------------------
 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();
+	while (m_loader.remaining() > 0) ;
 
-		return;
-	}
+	check_load_queue();
 }
 
 //-----------------------------------------------------------------------------
@@ -238,30 +156,17 @@ uint32_t ResourceManager::seed() const
 //-----------------------------------------------------------------------------
 void ResourceManager::check_load_queue()
 {
-	m_loading_mutex.lock();
-
-	if (m_loading_queue.size() > 0)
+	if (m_loader.num_loaded() != 0)
 	{
-		m_loading_requests.signal();
-	}
-
-	m_loading_mutex.unlock();
-}
+		TempAllocator1024 alloc;
+		List<LoadedResource> loaded(alloc);
+		m_loader.get_loaded(loaded);
 
-//-----------------------------------------------------------------------------
-void ResourceManager::bring_loaded_online()
-{
-	m_loaded_mutex.lock();
-
-	while (m_loaded_queue.size() > 0)
-	{
-		LoadedResource lr = m_loaded_queue.front();
-		m_loaded_queue.pop_front();
-
-		online(lr.resource, lr.data);
+		for (uint32_t i = 0; i < loaded.size(); i++)
+		{
+			online(loaded[i].resource, loaded[i].data);
+		}
 	}
-
-	m_loaded_mutex.unlock();
 }
 
 //-----------------------------------------------------------------------------
@@ -288,9 +193,8 @@ ResourceId ResourceManager::load(uint32_t name, uint32_t type)
 
 		m_resources.push_back(entry);
 
-		m_loading_mutex.lock();
-		m_loading_queue.push_back(id);
-		m_loading_mutex.unlock();
+		// Issue request to resource loader
+		m_loader.load(id);
 
 		return id;
 	}
@@ -301,66 +205,6 @@ ResourceId ResourceManager::load(uint32_t name, uint32_t type)
 	return entry->id;
 }
 
-//-----------------------------------------------------------------------------
-void ResourceManager::background_load()
-{
-	while (m_background_thread_should_run)
-	{
-		m_loading_mutex.lock();
-		while (m_loading_queue.size() == 0)
-		{
-			m_loading_requests.wait(m_loading_mutex);
-		}
-
-		ResourceId resource = m_loading_queue.front();
-		m_loading_queue.pop_front();
-
-		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();
-
-		m_loading_mutex.lock();
-		if (m_loading_queue.size() == 0)
-		{
-			m_all_loaded.signal();
-		}
-		m_loading_mutex.unlock();
-	}
-}
-
-//-----------------------------------------------------------------------------
-void* ResourceManager::load_by_type(ResourceId name)
-{
-	switch (name.type)
-	{
-		case TEXTURE_TYPE: return TextureResource::load(m_resource_allocator, m_resource_bundle, name);
-		case MESH_TYPE: return MeshResource::load(m_resource_allocator, m_resource_bundle, name);
-		case SOUND_TYPE: return SoundResource::load(m_resource_allocator, m_resource_bundle, name);
-		default: return NULL;
-	}
-}
-
-//-----------------------------------------------------------------------------
-void ResourceManager::unload_by_type(ResourceId name, void* resource)
-{
-	switch (name.type)
-	{
-		case TEXTURE_TYPE: return TextureResource::unload(m_resource_allocator, resource);
-		case MESH_TYPE: return MeshResource::unload(m_resource_allocator, resource);
-		case SOUND_TYPE: return SoundResource::unload(m_resource_allocator, resource);
-	}
-
-	return;
-}
-
 //-----------------------------------------------------------------------------
 void ResourceManager::online(ResourceId name, void* resource)
 {
@@ -383,21 +227,9 @@ void ResourceManager::online(ResourceId name, void* resource)
 		}
 	}
 
-	m_resources_mutex.lock();
-
 	ResourceEntry& entry = m_resources[name.index];
 	entry.resource = resource;
 	entry.state = RS_LOADED;
-
-	m_resources_mutex.unlock();
-}
-
-//-----------------------------------------------------------------------------
-void* ResourceManager::background_thread(void* thiz)
-{
-	((ResourceManager*)thiz)->background_load();
-
-	return NULL;
 }
 
 } // namespace crown

+ 8 - 63
engine/resource/ResourceManager.h

@@ -28,40 +28,22 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include "Types.h"
 #include "List.h"
-#include "Queue.h"
 #include "Resource.h"
 #include "HeapAllocator.h"
-#include "Thread.h"
-#include "Mutex.h"
-#include "Cond.h"
+#include "ResourceLoader.h"
 
 namespace crown
 {
 
 struct ResourceEntry
 {
+	bool operator==(const ResourceId& resource) { return id == resource; }
+	bool operator==(const ResourceEntry& b) { return id == b.id; }
+
 	ResourceId		id;
 	ResourceState	state;
-
 	uint32_t		references;
-
 	void*			resource;
-
-	bool			operator==(const ResourceId& resource)
-					{
-						return id == resource;
-					}
-
-	bool			operator==(const ResourceEntry& b)
-					{
-						return id == b.id;
-					}
-};
-
-struct LoadedResource
-{
-	ResourceId	resource;
-	void*		data;
 };
 
 class Bundle;
@@ -71,7 +53,7 @@ class ResourceManager
 {
 public:
 
-	/// Read resources from @a bundle and store resource data using @a allocator.
+	/// The resources will be loaded from @a bundle.
 							ResourceManager(Bundle& bundle);
 							~ResourceManager();
 
@@ -89,9 +71,6 @@ public:
 	/// (Such as texture objects, vertex buffers etc.)
 	void					unload(ResourceId name);
 
-	/// Reloads the @a resource
-	void					reload(ResourceId name);
-
 	/// Returns whether the manager has the @a name resource into
 	/// its list of resources.
 	/// @note
@@ -114,9 +93,6 @@ public:
 	/// Returns the number of references to the @a resource
 	uint32_t				references(ResourceId name) const;
 
-	/// Returns the number of resources still waiting to load.
-	uint32_t				remaining() const;
-
 	/// Forces all the loading requests to complete before preceeding.
 	void					flush();
 
@@ -128,51 +104,20 @@ 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);
-
-	void					background_load();
-
-	void*					load_by_type(ResourceId name);
 	void					unload_by_type(ResourceId name, void* resource);
 	void					online(ResourceId name, void* resource);
 
 private:
 
-	static void*			background_thread(void* thiz);
-
-private:
-
-	// Archive whether to look for resources
-	Bundle&					m_resource_bundle;
-	// Used to strore resource memory
-	HeapAllocator			m_resource_allocator;
-
 	HeapAllocator			m_allocator;
-	// The master lookup table
-	List<ResourceEntry>		m_resources;
-
-	// Resources waiting for loading
-	Queue<ResourceId>		m_loading_queue;
-	// Resources already loaded, ready to bring online
-	Queue<LoadedResource>	m_loaded_queue;
-
+	ResourceLoader			m_loader;
 	uint32_t				m_seed;
+	List<ResourceEntry>		m_resources;
 
-	// Background loading thread
-	bool 					m_background_thread_should_run;
-	os::Thread				m_thread;
-
-	mutable os::Mutex		m_loading_mutex;
-	os::Cond 				m_loading_requests;
-	os::Cond 				m_all_loaded;
-
-	os::Mutex				m_loaded_mutex;
-	mutable os::Mutex		m_resources_mutex;
+private:
 
 	friend class			Device;
 };