Explorar o código

Get rid of Cond

Daniele Bartolini %!s(int64=11) %!d(string=hai) anos
pai
achega
8812d6380f

+ 0 - 1
engine/Crown.h

@@ -109,7 +109,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 // Engine/Os
 #include "Thread.h"
 #include "Mutex.h"
-#include "Cond.h"
 #include "OsFile.h"
 #include "OsWindow.h"
 #include "OsSocket.h"

+ 1 - 1
engine/Device.cpp

@@ -375,7 +375,7 @@ void Device::frame()
 
 	if (!m_is_paused)
 	{
-		m_resource_manager->poll_resource_loader();
+		m_resource_manager->complete_requests();
 
 		m_lua_environment->call_global("frame", 1, ARGUMENT_FLOAT, last_delta_time());
 

+ 0 - 1
engine/core/thread/Semaphore.h

@@ -29,7 +29,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Config.h"
 #include "Assert.h"
 #include "Mutex.h"
-#include "Cond.h"
 
 #if CROWN_PLATFORM_POSIX
 	#include <pthread.h>

+ 0 - 29
engine/os/android/Cond.h

@@ -1,29 +0,0 @@
-/*
-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 "../posix/Cond.h"

+ 0 - 29
engine/os/linux/Cond.h

@@ -1,29 +0,0 @@
-/*
-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 "../posix/Cond.h"

+ 0 - 98
engine/os/posix/Cond.h

@@ -1,98 +0,0 @@
-/*
-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 <pthread.h>
-#include <cstring>
-
-#include "Types.h"
-#include "Mutex.h"
-#include "OS.h"
-
-namespace crown
-{
-
-class Cond
-{
-public:
-
-					Cond();
-					~Cond();
-
-	void			signal();
-	void			wait(Mutex& mutex);
-
-private:
-
-	pthread_cond_t	m_cond;
-
-private:
-
-	// Disable copying.
-					Cond(const Cond&);
-	Cond&			operator=(const Cond&);
-};
-
-//-----------------------------------------------------------------------------
-inline Cond::Cond()
-{
-	memset(&m_cond, 0, sizeof(pthread_cond_t));
-
-	int32_t result = pthread_cond_init(&m_cond, NULL);
-
-	CE_ASSERT(result == 0, "Failed to init cond. errno: %d", result);
-	CE_UNUSED(result);
-}
-
-//-----------------------------------------------------------------------------
-inline Cond::~Cond()
-{
-	int32_t result = pthread_cond_destroy(&m_cond);
-
-	CE_ASSERT(result == 0, "Failed to destroy cond. errno: %d", result);
-	CE_UNUSED(result);
-}
-
-//-----------------------------------------------------------------------------
-inline void Cond::signal()
-{
-	int32_t result = pthread_cond_signal(&m_cond);
-
-	CE_ASSERT(result == 0, "Failed to signal cond. errno: %d", result);
-	CE_UNUSED(result);
-}
-
-//-----------------------------------------------------------------------------
-inline void Cond::wait(Mutex& mutex)
-{
-	int32_t result = pthread_cond_wait(&m_cond, &(mutex.m_mutex));
-
-	CE_ASSERT(result == 0, "Failed to wait cond. errno: %d", result);
-	CE_UNUSED(result);
-}
-
-} // namespace crown

+ 0 - 82
engine/os/win/Cond.h

@@ -1,82 +0,0 @@
-/*
-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 "WinHeaders.h"
-#include <WinBase.h>
-#include <Synchapi.h>
-#include "Types.h"
-#include "Mutex.h"
-#include "OS.h"
-
-namespace crown
-{
-
-class Cond
-{
-public:
-
-						Cond();
-						~Cond();
-
-	void				signal();
-	void				wait(Mutex& mutex);
-
-private:
-
-						Cond(const Cond&);
-	Cond&				operator=(const Cond&);
-
-private:
-
-	CONDITION_VARIABLE	m_cond;
-};
-
-//-----------------------------------------------------------------------------
-inline Cond::Cond()
-{
-	InitializeConditionVariable(&m_cond);
-}
-
-//-----------------------------------------------------------------------------
-inline Cond::~Cond()
-{
-}
-
-//-----------------------------------------------------------------------------
-inline void Cond::signal()
-{
-	WakeConditionVariable(&m_cond);
-}
-
-//-----------------------------------------------------------------------------
-inline void Cond::wait(Mutex& mutex)
-{
-	SleepConditionVariableCS(&m_cond, &mutex.m_cs, INFINITE);
-}
-
-} // namespace crown

+ 56 - 62
engine/resource/ResourceLoader.cpp

@@ -33,94 +33,88 @@ namespace crown
 {
 
 //-----------------------------------------------------------------------------
-ResourceLoader::ResourceLoader(Bundle& bundle, Allocator& resource_heap) :
-	m_thread(),
-	m_should_run(false),
-	m_bundle(bundle),
-	m_resource_heap(resource_heap),
-	m_num_requests(0),
-	m_requests(default_allocator())
+ResourceLoader::ResourceLoader(Bundle& bundle, Allocator& resource_heap)
+	: m_thread()
+	, m_bundle(bundle)
+	, m_resource_heap(resource_heap)
+	, m_requests(default_allocator())
+	, m_loaded(default_allocator())
+	, m_exit(false)
 {
-	for (uint32_t i = 0; i < MAX_LOAD_REQUESTS; i++)
-	{
-		m_results[i].status = LRS_NO_INFORMATION;
-		m_results[i].data = NULL;
-	}
+	m_thread.start(ResourceLoader::thread_proc, this);
 }
 
-//-----------------------------------------------------------------------------
-LoadResourceId ResourceLoader::load_resource(ResourceId id)
+ResourceLoader::~ResourceLoader()
 {
-	m_requests_mutex.lock();
-
-	LoadResourceId lr_id = m_num_requests++;
-	LoadResource lr;
-	lr.id = lr_id;
-	lr.resource = id;
-
-	queue::push_back(m_requests, lr);
-
-	m_results[lr_id % MAX_LOAD_REQUESTS].status = LRS_QUEUED;
+	m_exit = true;
+}
 
-	m_requests_mutex.unlock();
+//-----------------------------------------------------------------------------
+void ResourceLoader::load(ResourceId id)
+{	
+	add_request(id);
+}
 
-	m_full.signal();
+//-----------------------------------------------------------------------------
+void ResourceLoader::flush()
+{
+	while (num_requests()) {}
+}
 
-	return lr_id;
+//-----------------------------------------------------------------------------
+void ResourceLoader::add_request(ResourceId id)
+{
+	ScopedMutex sm(m_mutex);
+	queue::push_back(m_requests, id);
 }
 
 //-----------------------------------------------------------------------------
-LoadResourceStatus ResourceLoader::load_resource_status(LoadResourceId id) const
+uint32_t ResourceLoader::num_requests()
 {
-	if (m_num_requests - id > MAX_LOAD_REQUESTS)
-	{
-		return LRS_NO_INFORMATION;
-	}
+	ScopedMutex sm(m_mutex);
+	return queue::size(m_requests);
+}
 
-	return m_results[id % MAX_LOAD_REQUESTS].status;
+//-----------------------------------------------------------------------------
+void ResourceLoader::add_loaded(ResourceData data)
+{
+	ScopedMutex sm(m_loaded_mutex);
+	queue::push_back(m_loaded, data);
 }
 
 //-----------------------------------------------------------------------------
-void* ResourceLoader::load_resource_data(LoadResourceId id) const
+void ResourceLoader::get_loaded(Array<ResourceData>& loaded)
 {
-	if (m_num_requests - id > MAX_LOAD_REQUESTS)
+	ScopedMutex sm(m_loaded_mutex);
+	uint32_t num = queue::size(m_loaded);
+	for (uint32_t i = 0; i < num; i++)
 	{
-		return NULL;
+		array::push_back(loaded, queue::front(m_loaded));
+		queue::pop_front(m_loaded);
 	}
-
-	return m_results[id % MAX_LOAD_REQUESTS].data;
 }
 
 //-----------------------------------------------------------------------------
 int32_t ResourceLoader::run()
 {
-	while (m_should_run)
+	while (!m_exit)
 	{
-		m_requests_mutex.lock();
-		while (queue::empty(m_requests) && m_should_run)
-		{
-			m_full.wait(m_requests_mutex);
-		}
-
-		if (m_should_run)
-		{
-			LoadResource request = queue::front(m_requests);
-			queue::pop_front(m_requests);
-
-			m_requests_mutex.unlock();
-
-			m_results[request.id % MAX_LOAD_REQUESTS].status = LRS_LOADING;
-
-			void* data = resource_on_load(request.resource.type, m_resource_heap, m_bundle, request.resource);
-
-			m_results[request.id % MAX_LOAD_REQUESTS].data = data;
-			m_results[request.id % MAX_LOAD_REQUESTS].status = LRS_LOADED;
-		}
-		else
+		m_mutex.lock();
+		if (queue::empty(m_requests))
 		{
-			// Release the mutex when exiting
-			m_requests_mutex.unlock();
+			m_mutex.unlock();
+			continue;
 		}
+		ResourceId id = queue::front(m_requests);
+		m_mutex.unlock();
+
+		ResourceData rd;
+		rd.id = id;
+		rd.data = resource_on_load(id.type, m_resource_heap, m_bundle, id);
+		add_loaded(rd);
+		m_mutex.lock();
+		queue::pop_front(m_requests);
+		m_mutex.unlock();
 	}
 
 	return 0;

+ 22 - 54
engine/resource/ResourceLoader.h

@@ -31,7 +31,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Thread.h"
 #include "ContainerTypes.h"
 #include "Mutex.h"
-#include "Cond.h"
+#include "Semaphore.h"
 #include "OS.h"
 
 namespace crown
@@ -40,26 +40,9 @@ namespace crown
 class Bundle;
 class Allocator;
 
-#define MAX_LOAD_REQUESTS 1024
-typedef uint32_t LoadResourceId;
-
-enum LoadResourceStatus
-{
-	LRS_NO_INFORMATION,
-	LRS_QUEUED,
-	LRS_LOADING,
-	LRS_LOADED
-};
-
-struct LoadResource
+struct ResourceData
 {
-	LoadResourceId id;
-	ResourceId resource;
-};
-
-struct LoadResourceData
-{
-	LoadResourceStatus status;
+	ResourceId id;
 	void* data;
 };
 
@@ -71,57 +54,42 @@ public:
 	/// Reads the resources data from the given @a bundle using
 	/// @a resource_heap to allocate memory for them.
 	ResourceLoader(Bundle& bundle, Allocator& resource_heap);
+	~ResourceLoader();
 
 	/// Loads the @a resource in a background thread.
-	LoadResourceId load_resource(ResourceId id);
+	void load(ResourceId id);
 
-	/// Returns the status of the given load request @a id.
-	LoadResourceStatus load_resource_status(LoadResourceId id) const;
+	/// Blocks until all pending requests have been processed.
+	void flush();
 
-	/// Returns the data which has been loaded for the given request @a id.
-	void* load_resource_data(LoadResourceId id) const;
+	void get_loaded(Array<ResourceData>& loaded);
 
-	// Loads resources in the loading queue.
-	int32_t run();
-
-	void start()
-	{
-		m_should_run = true;
-		m_thread.start(background_run, this);
-	}
+private:
 
-	void stop()
-	{
-		m_should_run = false;
-		m_full.signal();
-		m_thread.stop();
-	}
+	void add_request(ResourceId id);
+	uint32_t num_requests();
+	void add_loaded(ResourceData data);
 
-private:
+	// Loads resources in the loading queue.
+	int32_t run();
 
-	static int32_t background_run(void* thiz)
+	static int32_t thread_proc(void* thiz)
 	{
-		return ((ResourceLoader*)thiz)->run();
+		ResourceLoader* rl = (ResourceLoader*)thiz;
+		return rl->run();
 	}
 
 private:
 
 	Thread m_thread;
-	bool m_should_run;
-
-	// Whether to look for resources
 	Bundle& m_bundle;
-
-	// Used to strore resource memory
 	Allocator& m_resource_heap;
 
-	uint32_t m_num_requests;
-	Queue<LoadResource> m_requests;
-	LoadResourceData m_results[MAX_LOAD_REQUESTS];
-
-	Mutex m_requests_mutex;
-	Mutex m_results_mutex;
-	Cond m_full;
+	Queue<ResourceId> m_requests;
+	Queue<ResourceData> m_loaded;
+	Mutex m_mutex;
+	Mutex m_loaded_mutex;
+	bool m_exit;
 };
 
 } // namespace crown

+ 20 - 45
engine/resource/ResourceManager.cpp

@@ -34,6 +34,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "TempAllocator.h"
 #include "DynamicString.h"
 #include "Queue.h"
+#include "Log.h"
 
 namespace crown
 {
@@ -48,16 +49,8 @@ ResourceId::ResourceId(const char* type, const char* name)
 ResourceManager::ResourceManager(Bundle& bundle)
 	: m_resource_heap("resource", default_allocator())
 	, m_loader(bundle, m_resource_heap)
-	, m_pendings(default_allocator())
 	, m_resources(default_allocator())
 {
-	m_loader.start();
-}
-
-//-----------------------------------------------------------------------------
-ResourceManager::~ResourceManager()
-{
-	m_loader.stop();
 }
 
 //-----------------------------------------------------------------------------
@@ -66,24 +59,10 @@ void ResourceManager::load(ResourceId id)
 	// Search for an already existent resource
 	ResourceEntry* entry = find(id);
 
-	// If resource not found, create a new one
+	// If resource not found, post load request
 	if (entry == NULL)
 	{
-		ResourceEntry entry;
-
-		entry.id = id;
-		entry.references = 1;
-		entry.resource = NULL;
-
-		array::push_back(m_resources, entry);
-
-		// Issue request to resource loader
-		PendingRequest pr;
-		pr.resource = id;
-		pr.id = m_loader.load_resource(id);
-
-		queue::push_back(m_pendings, pr);
-
+		m_loader.load(id);
 		return;
 	}
 
@@ -96,6 +75,8 @@ void ResourceManager::unload(ResourceId id, bool force)
 {
 	CE_ASSERT(has(id), "Resource not loaded: %.16lx-%16lx", id.type, id.name);
 
+	flush();
+
 	ResourceEntry* entry = find(id);
 
 	entry->references--;
@@ -158,10 +139,8 @@ uint32_t ResourceManager::references(ResourceId id) const
 //-----------------------------------------------------------------------------
 void ResourceManager::flush()
 {
-	while (!queue::empty(m_pendings))
-	{
-		poll_resource_loader();
-	}
+	m_loader.flush();
+	complete_requests();
 }
 
 //-----------------------------------------------------------------------------
@@ -173,29 +152,25 @@ ResourceEntry* ResourceManager::find(ResourceId id) const
 }
 
 //-----------------------------------------------------------------------------
-void ResourceManager::poll_resource_loader()
+void ResourceManager::complete_requests()
 {
-	if (!queue::empty(m_pendings))
-	{
-		PendingRequest request = queue::front(m_pendings);
+	TempAllocator1024 ta;
+	Array<ResourceData> loaded(ta);
+	m_loader.get_loaded(loaded);
 
-		if (m_loader.load_resource_status(request.id) == LRS_LOADED)
-		{
-			queue::pop_front(m_pendings);
-
-			void* data = m_loader.load_resource_data(request.id);
-			online(request.resource, data);
-		}
-	}
+	for (uint32_t i = 0; i < array::size(loaded); i++)
+		complete_request(loaded[i].id, loaded[i].data);
 }
 
 //-----------------------------------------------------------------------------
-void ResourceManager::online(ResourceId id, void* resource)
+void ResourceManager::complete_request(ResourceId id, void* data)
 {
-	ResourceEntry* entry = find(id);
-	resource_on_online(id.type, resource);
-
-	entry->resource = resource;
+	resource_on_online(id.type, data);
+	ResourceEntry entry;
+	entry.id = id;
+	entry.references = 1;
+	entry.resource = data;
+	array::push_back(m_resources, entry);
 }
 
 } // namespace crown

+ 2 - 12
engine/resource/ResourceManager.h

@@ -45,12 +45,6 @@ struct ResourceEntry
 	void* resource;
 };
 
-struct PendingRequest
-{
-	LoadResourceId id;
-	ResourceId resource;
-};
-
 class Bundle;
 
 /// Keeps track and manages resources loaded by ResourceLoader.
@@ -60,7 +54,6 @@ public:
 
 	/// The resources will be loaded from @a bundle.
 	ResourceManager(Bundle& bundle);
-	~ResourceManager();
 
 	/// Loads the resource by @a type and @a name and returns its ResourceId.
 	/// @note
@@ -106,21 +99,18 @@ private:
 	ResourceEntry* find(ResourceId id) const;
 
 	// Polls the resource loader for loaded resources.
-	void poll_resource_loader();
+	void complete_requests();
 
-	void online(ResourceId id, void* resource);
+	void complete_request(ResourceId id, void* data);
 
 private:
 
 	ProxyAllocator m_resource_heap;
 	ResourceLoader m_loader;
-
-	Queue<PendingRequest> m_pendings;
 	Array<ResourceEntry> m_resources;
 
 private:
 
-	friend struct ResourcePackage;
 	friend class Device;
 };