Browse Source

Removing exceptions

Panagiotis Christopoulos Charitos 11 years ago
parent
commit
16ca1ceaae

+ 9 - 7
include/anki/scene/StaticGeometryNode.h

@@ -41,12 +41,13 @@ class StaticGeometryPatchNode: public SceneNode, public SpatialComponent,
 	public RenderComponent
 {
 public:
-	StaticGeometryPatchNode(
-		const CString& name, SceneGraph* scene, // Scene
-		const ModelPatchBase* modelPatch); // Self
+	StaticGeometryPatchNode(SceneGraph* scene);
 
 	~StaticGeometryPatchNode();
 
+	ANKI_USE_RESULT Error create(
+		const CString& name, const ModelPatchBase* modelPatch);
+
 	/// @name SpatialComponent virtuals
 	/// @{
 	const CollisionShape& getSpatialCollisionShape()
@@ -62,7 +63,7 @@ public:
 
 	/// @name RenderComponent virtuals
 	/// @{
-	void buildRendering(RenderingBuildData& data);
+	ANKI_USE_RESULT Error buildRendering(RenderingBuildData& data);
 
 	const Material& getMaterial()
 	{
@@ -79,12 +80,13 @@ private:
 class StaticGeometryNode: public SceneNode
 {
 public:
-	StaticGeometryNode(
-		const CString& name, SceneGraph* scene, // Scene
-		const CString& filename); // Self
+	StaticGeometryNode(SceneGraph* scene);
 
 	~StaticGeometryNode();
 
+	ANKI_USE_RESULT Error create(
+		const CString& name, const CString& filename);
+
 private:
 	ModelResourcePointer m_model;
 };

+ 63 - 21
include/anki/scene/Visibility.h

@@ -42,16 +42,12 @@ enum VisibleBy
 class VisibleNode: public NonCopyable
 {
 public:
-	SceneNode* m_node;
+	SceneNode* m_node = nullptr;
 	/// An array of the visible spatials
-	U8* m_spatialIndices;
-	U8 m_spatialsCount;
+	U8* m_spatialIndices = nullptr;
+	U8 m_spatialsCount = 0;
 
-	VisibleNode()
-	:	m_node(nullptr), 
-		m_spatialIndices(nullptr), 
-		m_spatialsCount(0)
-	{}
+	VisibleNode() = default;
 
 	VisibleNode(VisibleNode&& other)
 	{
@@ -82,22 +78,66 @@ public:
 class VisibilityTestResults
 {
 public:
-	typedef SceneFrameVector<VisibleNode> Container;
+	using Container = SceneFrameDArray<VisibleNode>;
 
-	Container m_renderables;
-	Container m_lights;
+	~VisibilityTestResults()
+	{
+		ANKI_ASSERT(0 && "It's supposed to be deallocated on frame start");
+	}
+
+	ANKI_USE_RESULT Error create(
+		SceneAllocator<U8> alloc,
+		U32 renderablesReservedSize,
+		U32 lightsReservedSize)
+	{
+		Error err = m_renderables.create(alloc, renderablesReservedSize);
+		if(!err)
+		{
+			err = m_lights.create(alloc, lightsReservedSize);
+		}
+		return err;
+	}
+
+	VisibleNode* getRenderablesBegin()
+	{
+		return &m_renderables[0];
+	}
+
+	VisibleNode* getRenderablesEnd()
+	{
+		return &m_renderables[0] + m_renderablesCount;
+	}
 
-	VisibilityTestResults(const SceneAllocator<U8>& frameAlloc,
-		U32 renderablesReservedSize = 
-			ANKI_FRUSTUMABLE_AVERAGE_VISIBLE_RENDERABLES_COUNT,
-		U32 lightsReservedSize =
-			ANKI_FRUSTUMABLE_AVERAGE_VISIBLE_LIGHTS_COUNT)
-	:	m_renderables(frameAlloc), 
-		m_lights(frameAlloc)
+	VisibleNode* getLightsBegin()
 	{
-		m_renderables.reserve(renderablesReservedSize);
-		m_lights.reserve(lightsReservedSize);
+		return &m_lights[0];
 	}
+
+	VisibleNode* getLightsEnd()
+	{
+		return &m_lights[0] + m_lightsCount;
+	}
+
+	ANKI_USE_RESULT Error moveBackRenderable(
+		SceneAllocator<U8> alloc, VisibleNode& x)
+	{
+		return moveBack(alloc, m_renderables, m_renderablesCount, x);
+	}
+
+	ANKI_USE_RESULT Error moveBackLight(
+		SceneAllocator<U8> alloc, VisibleNode& x)
+	{
+		return moveBack(alloc, m_lights, m_lightsCount, x);
+	}
+
+private:
+	Container m_renderables;
+	Container m_lights;
+	U32 m_renderablesCount = 0;
+	U32 m_lightsCount = 0;
+
+	ANKI_USE_RESULT Error moveBack(
+		SceneAllocator<U8> alloc, Container& c, U32& count, VisibleNode& x);
 };
 
 /// Sort spatial scene nodes on distance
@@ -162,7 +202,9 @@ public:
 };
 
 /// Do visibility tests bypassing portals 
-void doVisibilityTests(SceneNode& frustumable, SceneGraph& scene, 
+ANKI_USE_RESULT Error doVisibilityTests(
+	SceneNode& frustumable, 
+	SceneGraph& scene, 
 	Renderer& renderer);
 
 /// @}

+ 1 - 1
include/anki/util/DArray.h

@@ -191,7 +191,7 @@ public:
 			PtrSize minSize = std::min<PtrSize>(size, m_size);
 			for(U i = 0; i < minSize; i++)
 			{
-				newArr[i] = (*this)[i];
+				newArr[i] = std::move((*this)[i]);
 			}
 
 			destroy(alloc);

+ 5 - 38
include/anki/util/Functions.h

@@ -10,8 +10,9 @@
 #define ANKI_UTIL_FUNCTIONS_H
 
 #include "anki/util/StdTypes.h"
-#include "anki/util/String.h"
+#include "anki/util/Assert.h"
 #include <cmath>
+#include <utility>
 
 namespace anki {
 
@@ -100,33 +101,6 @@ inline Bool isAligned(PtrSize alignment, Type value)
 	return ((PtrSize)value % alignment) == 0;
 }
 
-/// Get the size in bytes of a vector
-template<typename Vec>
-inline PtrSize getVectorSizeInBytes(const Vec& v)
-{
-	return v.size() * sizeof(typename Vec::value_type);
-}
-
-/// Delete a pointer properly 
-template<typename T>
-inline void propperDelete(T*& x)
-{
-	typedef char TypeMustBeComplete[sizeof(T) ? 1 : -1];
-  	(void) sizeof(TypeMustBeComplete);
-	delete x;
-	x = nullptr;
-}
-
-/// Delete a pointer properly
-template<typename T>
-inline void propperDeleteArray(T*& x)
-{
-	typedef char TypeMustBeComplete[sizeof(T) ? 1 : -1];
-	(void) sizeof(TypeMustBeComplete);
-	delete[] x;
-	x = nullptr;
-}
-
 /// A simple template trick to remove the pointer from one type
 ///
 /// Example:
@@ -167,14 +141,7 @@ inline U32 countBits(U32 number)
 #endif
 }
 
-/// Get the underlying type of a strongly typed enum
-template<typename TEnum>
-constexpr typename std::underlying_type<TEnum>::type enumValue(TEnum val)
-{
-	return static_cast<typename std::underlying_type<TEnum>::type>(val);
-}
-
-/// Construct an object
+/// Call an object constructor.
 template<typename T, typename... TArgs>
 void construct(T* p, TArgs&&... args)
 {
@@ -182,9 +149,9 @@ void construct(T* p, TArgs&&... args)
 	::new(reinterpret_cast<void*>(p)) T(std::forward<TArgs>(args)...);
 }
 
-/// Call destructor
+/// Call destructor.
 template<typename T>
-void destroy(T* p)
+void destruct(T* p)
 {
 	p->~T();
 }

+ 8 - 0
include/anki/util/StdTypes.h

@@ -137,6 +137,14 @@ public:
 		return m_code != ErrorCode::NONE;
 	}
 
+	/// @privatesection
+	/// @{
+	ErrorCode _getCode() const
+	{
+		return m_code;
+	}
+	/// @}
+
 private:
 	ErrorCode m_code = ErrorCode::NONE;
 };

+ 15 - 15
include/anki/util/Thread.h

@@ -36,7 +36,7 @@ public:
 	};
 
 	/// The type of the tread callback
-	using Callback = I(*)(Info&);
+	using Callback = Error(*)(Info&);
 
 	/// Create a thread with or without a name
 	/// @param[in] name The name of the new thread. Can be nullptr
@@ -51,7 +51,7 @@ public:
 
 	/// Wait for the thread to finish
 	/// @return The error code of the thread's callback
-	I join();
+	ANKI_USE_RESULT Error join();
 
 	/// Identify the current thread
 	static Id getCurrentThreadId();
@@ -125,10 +125,7 @@ public:
 
 	/// Bock until signaled.
 	/// @param mtx The mutex.
-	/// @param timeoutSeconds Wait for the specified time. If zero it waits 
-	///                       forever.
-	/// @return On timeout it returns true.
-	Bool wait(Mutex& mtx, F64 timeoutSeconds = 0.0);
+	void wait(Mutex& mtx);
 
 private:
 	void* m_impl = nullptr; ///< The system native type
@@ -192,10 +189,7 @@ public:
 	~Barrier() = default;
 
 	/// Wait until all threads call wait().
-	/// @param timeoutSeconds Wait for the specified time. If zero it waits 
-	///                       forever.
-	/// @return On timeout it returns true.
-	Bool wait(F64 timeoutSeconds = 0.0);
+	Bool wait();
 
 private:
 	Mutex m_mtx;
@@ -226,7 +220,7 @@ public:
 		virtual ~Task()
 		{}
 
-		virtual void operator()(U32 taskId, PtrSize threadsCount) = 0;
+		virtual Error operator()(U32 taskId, PtrSize threadsCount) = 0;
 
 		/// Chose a starting and end index
 		static void choseStartEnd(U32 taskId, PtrSize threadsCount, 
@@ -249,12 +243,16 @@ public:
 	/// @param task The task. If it's nullptr then a dummy task will be assigned
 	void assignNewTask(U32 slot, Task* task);
 
-	/// Wait for all tasks to finish
-	void waitForAllThreadsToFinish()
+	/// Wait for all tasks to finish.
+	/// @return The error code in one of the worker threads.
+	ANKI_USE_RESULT Error waitForAllThreadsToFinish()
 	{
 #if !ANKI_DISABLE_THREADPOOL_THREADING
 		m_barrier.wait();
 #endif
+		Error err = m_err;
+		m_err = ErrorCode::NONE;
+		return err;
 	}
 
 	PtrSize getThreadsCount() const
@@ -267,18 +265,20 @@ private:
 	class DummyTask: public Task
 	{
 	public:
-		void operator()(U32 taskId, PtrSize threadsCount)
+		Error operator()(U32 taskId, PtrSize threadsCount)
 		{
 			(void)taskId;
 			(void)threadsCount;
+			return ErrorCode::NONE;
 		}
 	};
 
 #if !ANKI_DISABLE_THREADPOOL_THREADING
 	Barrier m_barrier; ///< Synchronization barrier
-	detail::ThreadpoolThread** m_threads = nullptr; ///< Threads array
+	detail::ThreadpoolThread* m_threads = nullptr; ///< Threads array
 #endif
 	U8 m_threadsCount = 0;
+	Error m_err = ErrorCode::NONE;
 	static DummyTask m_dummyTask;
 };
 

+ 12 - 4
src/scene/Camera.cpp

@@ -23,14 +23,22 @@ Camera::Camera(SceneGraph* scene, Type type, Frustum* frustum)
 //==============================================================================
 Error Camera::create(const CString& name) 
 {
-	Error err = SceneNode::create(name, 3);
+	Error err = SceneNode::create(name);
 
 	// Init components
 	if(!err)
 	{
-		addComponent(static_cast<MoveComponent*>(this));
-		addComponent(static_cast<FrustumComponent*>(this));
-		addComponent(static_cast<SpatialComponent*>(this));
+		err = addComponent(static_cast<MoveComponent*>(this));
+	}
+
+	if(!err)
+	{
+		err = addComponent(static_cast<FrustumComponent*>(this));
+	}
+
+	if(!err)
+	{
+		err = addComponent(static_cast<SpatialComponent*>(this));
 	}
 
 	return err;

+ 109 - 40
src/scene/StaticGeometryNode.cpp

@@ -24,70 +24,112 @@ StaticGeometrySpatial::StaticGeometrySpatial(
 //==============================================================================
 
 //==============================================================================
-StaticGeometryPatchNode::StaticGeometryPatchNode(
-	const CString& name, SceneGraph* scene, const ModelPatchBase* modelPatch)
-:	SceneNode(name, scene),
+StaticGeometryPatchNode::StaticGeometryPatchNode(SceneGraph* scene)
+:	SceneNode(scene),
 	SpatialComponent(this),
-	RenderComponent(this),
-	m_modelPatch(modelPatch)
+	RenderComponent(this)
+{}
+
+//==============================================================================
+Error StaticGeometryPatchNode::create(
+	const CString& name, const ModelPatchBase* modelPatch)
 {
-	addComponent(static_cast<SpatialComponent*>(this));
-	addComponent(static_cast<RenderComponent*>(this));
+	ANKI_ASSERT(modelPatch);
+	Error err = ErrorCode::NONE;
+
+	m_modelPatch = modelPatch;
 
-	ANKI_ASSERT(m_modelPatch);
-	RenderComponent::init();
+	err = SceneNode::create(name);
+	
+	if(!err)
+	{
+		err = addComponent(static_cast<SpatialComponent*>(this));
+	}
 
-	// Check if multimesh
-	if(m_modelPatch->getSubMeshesCount() > 1)
+	if(!err)
 	{
-		// If multimesh create additional spatial components
+		err = addComponent(static_cast<RenderComponent*>(this));
+	}
 
-		m_obb = &m_modelPatch->getBoundingShapeSub(0);
+	if(!err)
+	{	
+		err = RenderComponent::create();
+	}
 
-		for(U i = 1; i < m_modelPatch->getSubMeshesCount(); i++)
+	if(!err)
+	{
+		// Check if multimesh
+		if(m_modelPatch->getSubMeshesCount() > 1)
+		{
+			// If multimesh create additional spatial components
+
+			m_obb = &m_modelPatch->getBoundingShapeSub(0);
+
+			for(U i = 1; i < m_modelPatch->getSubMeshesCount() && !err; i++)
+			{
+				StaticGeometrySpatial* spatial =
+					getSceneAllocator().newInstance<StaticGeometrySpatial>(
+					this, &m_modelPatch->getBoundingShapeSub(i));
+
+				if(spatial)
+				{
+					err = addComponent(static_cast<SpatialComponent*>(spatial));
+				}
+				else
+				{
+					err = ErrorCode::OUT_OF_MEMORY;
+				}
+			}
+		}
+		else
 		{
-			StaticGeometrySpatial* spatial =
-				getSceneAllocator().newInstance<StaticGeometrySpatial>(
-				this, &m_modelPatch->getBoundingShapeSub(i));
+			// If not multimesh then set the current spatial component
 
-			addComponent(static_cast<SpatialComponent*>(spatial));
+			m_obb = &modelPatch->getBoundingShape();
 		}
 	}
-	else
-	{
-		// If not multimesh then set the current spatial component
 
-		m_obb = &modelPatch->getBoundingShape();
-	}
+	return err;
 }
 
 //==============================================================================
 StaticGeometryPatchNode::~StaticGeometryPatchNode()
 {
 	U i = 0;
-	iterateComponentsOfType<SpatialComponent>([&](SpatialComponent& spatial)
+	Error err = iterateComponentsOfType<SpatialComponent>([&](
+		SpatialComponent& spatial)
 	{
 		if(i != 0)
 		{
 			getSceneAllocator().deleteInstance(&spatial);
 		}
 		++i;
+
+		return ErrorCode::NONE;
 	});
+
+	(void)err;
 }
 
 //==============================================================================
-void StaticGeometryPatchNode::buildRendering(RenderingBuildData& data)
+Error StaticGeometryPatchNode::buildRendering(RenderingBuildData& data)
 {
+	Error err = ErrorCode::NONE;
+
 	Array<U32, ANKI_GL_MAX_SUB_DRAWCALLS> indicesCountArray;
 	Array<PtrSize, ANKI_GL_MAX_SUB_DRAWCALLS> indicesOffsetArray;
 	U32 drawCount;
 	GlCommandBufferHandle vertJobs;
 	GlProgramPipelineHandle ppline;
 
-	m_modelPatch->getRenderingDataSub(
+	err = m_modelPatch->getRenderingDataSub(
 		data.m_key, vertJobs, ppline, 
 		data.m_subMeshIndicesArray, data.m_subMeshIndicesCount, 
 		indicesCountArray, indicesOffsetArray, drawCount);
+	if(err)
+	{
+		return err;
+	}
 
 	ppline.bind(data.m_jobs);
 	data.m_jobs.pushBackOtherCommandBuffer(vertJobs);
@@ -110,6 +152,8 @@ void StaticGeometryPatchNode::buildRendering(RenderingBuildData& data)
 		// TODO Make it indirect
 		ANKI_ASSERT(0 && "TODO");
 	}
+
+	return err;
 }
 
 //==============================================================================
@@ -117,25 +161,50 @@ void StaticGeometryPatchNode::buildRendering(RenderingBuildData& data)
 //==============================================================================
 
 //==============================================================================
-StaticGeometryNode::StaticGeometryNode(
-	const CString& name, SceneGraph* scene, const CString& filename)
-:	SceneNode(name, scene)
+StaticGeometryNode::StaticGeometryNode(SceneGraph* scene)
+:	SceneNode(scene)
 {
-	m_model.load(filename, &getResourceManager());
+}
 
-	U i = 0;
-	for(const ModelPatchBase* patch : m_model->getModelPatches())
-	{
-		SceneString newname(getSceneAllocator());
-		newname.sprintf("%s_%u", &name[0], i);
+//==============================================================================
+Error StaticGeometryNode::create(const CString& name, const CString& filename)
+{
+	Error err = SceneNode::create(name);
 
-		StaticGeometryPatchNode* node = 
-			getSceneGraph().newSceneNode<StaticGeometryPatchNode>(
-			newname.toCString(), patch);
-		(void)node;
+	if(!err)
+	{
+		err = m_model.load(filename, &getResourceManager());
+	}
 
-		++i;
+	if(!err)
+	{
+		U i = 0;
+		for(const ModelPatchBase* patch : m_model->getModelPatches())
+		{
+			SceneString newname;
+			
+			err = newname.sprintf(getSceneAllocator(), "%s_%u", &name[0], i);
+			if(err)
+			{
+				break;
+			}
+
+			StaticGeometryPatchNode* node;
+			err = getSceneGraph().newSceneNode<StaticGeometryPatchNode>(
+				newname.toCString(), node, patch);
+			
+			newname.destroy(getSceneAllocator());
+
+			if(err)
+			{
+				break;
+			}
+
+			++i;
+		}
 	}
+
+	return err;
 }
 
 //==============================================================================

+ 26 - 6
src/scene/Visibility.cpp

@@ -19,12 +19,12 @@ public:
 	U m_nodesCount = 0;
 	SceneGraph* m_scene = nullptr;
 	SceneNode* frustumableSn = nullptr;
-	SceneFrameAllocator<U8> frameAlloc;
+	SceneFrameAllocator<U8> m_alloc;
 
-	VisibilityTestResults* cameraVisible; // out
+	VisibilityTestResults* m_cameraVisible; // out
 
 	/// Test a frustum component
-	void test(SceneNode& testedNode, Bool isLight, 
+	ANKI_USE_RESULT Error test(SceneNode& testedNode, Bool isLight, 
 		U32 threadId, PtrSize threadsCount)
 	{
 		ANKI_ASSERT(isLight == 
@@ -155,14 +155,34 @@ public:
 	}
 
 	/// Do the tests
-	void operator()(U32 threadId, PtrSize threadsCount)
+	Error operator()(U32 threadId, PtrSize threadsCount)
 	{
-		test(*frustumableSn, false, threadId, threadsCount);
+		return test(*frustumableSn, false, threadId, threadsCount);
 	}
 };
 
 //==============================================================================
-void doVisibilityTests(SceneNode& fsn, SceneGraph& scene, 
+Error VisibilityTestResults::moveBack(
+	SceneAllocator<U8> alloc, Container& c, U32& count, VisibleNode& x)
+{
+	Error err = ErrorCode::NONE;
+
+	if(count + 1 > c.getSize())
+	{
+		// Need to grow
+		err = c.resize(alloc, c.getSize() * 2);
+	}
+
+	if(!err)
+	{
+		c[count++] = std::move(x);
+	}
+
+	return err;
+}
+
+//==============================================================================
+Error doVisibilityTests(SceneNode& fsn, SceneGraph& scene, 
 	Renderer& r)
 {
 	FrustumComponent& fr = fsn.getComponent<FrustumComponent>();

+ 42 - 22
src/util/Thread.cpp

@@ -5,7 +5,10 @@
 
 #include "anki/util/Thread.h"
 #include "anki/util/Assert.h"
-#include "anki/util/Exception.h"
+#include "anki/util/Logger.h"
+#include "anki/util/Functions.h"
+#include <cstdlib>
+#include <new>
 
 namespace anki {
 
@@ -14,28 +17,27 @@ namespace anki {
 //==============================================================================
 
 //==============================================================================
-Bool Barrier::wait(F64 timeoutSeconds)
+Bool Barrier::wait()
 {
 	m_mtx.lock();
 	U32 gen = m_generation;
-	Bool timeout = false;
 
 	if(--m_count == 0)
 	{
 		m_generation++;
 		m_count = m_threshold;
 		m_cond.notifyAll();
+		m_mtx.unlock();
+		return true;
 	}
-	else
+
+	while(gen == m_generation)
 	{
-		while(gen == m_generation)
-		{
-			timeout = m_cond.wait(m_mtx, timeoutSeconds);
-		}
+		m_cond.wait(m_mtx);
 	}
 
 	m_mtx.unlock();
-	return timeout;
+	return false;
 }
 
 //==============================================================================
@@ -81,7 +83,7 @@ public:
 
 private:
 	/// Thread callaback
-	static I threadCallback(Thread::Info& info)
+	static Error threadCallback(Thread::Info& info)
 	{
 		ThreadpoolThread& self = 
 			*reinterpret_cast<ThreadpoolThread*>(info.m_userData);
@@ -105,13 +107,19 @@ private:
 			}
 
 			// Exec
-			(*task)(self.m_id, threadCount);
+			Error err = (*task)(self.m_id, threadCount);
+
+			if(err)
+			{
+				LockGuard<Mutex> lock(mtx);
+				self.m_threadpool->m_err = err;
+			}
 
 			// Sync with main thread
 			barrier.wait();
 		}
 
-		return 0;
+		return ErrorCode::NONE;
 	}
 };
 
@@ -136,12 +144,17 @@ Threadpool::Threadpool(U32 threadsCount)
 	ANKI_ASSERT(m_threadsCount <= MAX_THREADS && m_threadsCount > 0);
 
 #if !ANKI_DISABLE_THREADPOOL_THREADING
-	m_threads = new detail::ThreadpoolThread*[m_threadsCount];
+	m_threads = reinterpret_cast<detail::ThreadpoolThread*>(
+		malloc(sizeof(detail::ThreadpoolThread) * m_threadsCount));
+
+	if(m_threads == nullptr)
+	{
+		ANKI_LOGF("Out of memory");
+	}
 
 	while(threadsCount-- != 0)
 	{
-		m_threads[threadsCount] = 
-			new detail::ThreadpoolThread(threadsCount, this);
+		construct(&m_threads[threadsCount], threadsCount, this);
 	}
 #endif
 }
@@ -154,23 +167,25 @@ Threadpool::~Threadpool()
 	U count = m_threadsCount;
 	while(count-- != 0)
 	{
-		detail::ThreadpoolThread& thread = *m_threads[count];
+		detail::ThreadpoolThread& thread = m_threads[count];
 
 		thread.m_quit = true;
 		thread.assignNewTask(&m_dummyTask); // Wake it
 	}
 
-	waitForAllThreadsToFinish();
+	Error err = waitForAllThreadsToFinish();
+	(void)err;
 
 	while(m_threadsCount-- != 0)
 	{
-		m_threads[m_threadsCount]->m_thread.join();
-		delete m_threads[m_threadsCount];
+		Error err = m_threads[m_threadsCount].m_thread.join();
+		(void)err;
+		m_threads[m_threadsCount].~ThreadpoolThread();
 	}
 
 	if(m_threads)
 	{
-		delete[] m_threads;
+		free(m_threads);
 	}
 #endif
 }
@@ -186,9 +201,14 @@ void Threadpool::assignNewTask(U32 slot, Task* task)
 		task = &m_dummyTask;
 	}
 	
-	m_threads[slot]->assignNewTask(task);
+	m_threads[slot].assignNewTask(task);
 #else
-	(*task)(slot, m_threadsCount);
+	Error err = (*task)(slot, m_threadsCount);
+
+	if(err)
+	{
+		m_err = err;
+	}
 #endif
 }
 

+ 20 - 57
src/util/ThreadPosix.cpp

@@ -4,7 +4,7 @@
 // http://www.anki3d.org/LICENSE
 
 #include "anki/util/Thread.h"
-#include "anki/util/Exception.h"
+#include "anki/util/Logger.h"
 #include <cstring>
 #include <algorithm>
 #include <pthread.h>
@@ -32,11 +32,9 @@ static void* pthreadCallback(void* ud)
 	info.m_userData = thread->_getUserData();
 	info.m_threadName = thread->_getName();
 
-	I err = thread->_getCallback()(info);
-	void* errVoidp = nullptr;
-	std::memcpy(&errVoidp, &err, sizeof(err));
+	Error err = thread->_getCallback()(info);
 
-	return nullptr;
+	return reinterpret_cast<void*>(static_cast<PtrSize>(err._getCode()));
 }
 
 //==============================================================================
@@ -45,7 +43,7 @@ Thread::Thread(const char* name)
 	m_impl = malloc(sizeof(pthread_t));
 	if(m_impl == nullptr)
 	{
-		throw ANKI_EXCEPTION("Out of memory");
+		ANKI_LOGF("Out of memory");
 	}
 
 	// Init the name
@@ -84,7 +82,7 @@ void Thread::start(void* userData, Callback callback)
 	I err = pthread_create(impl, nullptr, pthreadCallback, this);
 	if(err)
 	{
-		throw ANKI_EXCEPTION("pthread_create() failed");
+		ANKI_LOGF("pthread_create() failed");
 	}
 	else
 	{
@@ -95,16 +93,16 @@ void Thread::start(void* userData, Callback callback)
 }
 
 //==============================================================================
-I Thread::join()
+Error Thread::join()
 {
 	ANKI_ASSERT(m_started);
 	pthread_t* impl = reinterpret_cast<pthread_t*>(m_impl);
 
 	void* out;
-	U err = pthread_join(*impl, &out);
+	I err = pthread_join(*impl, &out);
 	if(err)
 	{
-		throw ANKI_EXCEPTION("pthread_join() failed");
+		ANKI_LOGF("pthread_join() failed");
 	}
 
 #if ANKI_ASSERTIONS
@@ -112,9 +110,8 @@ I Thread::join()
 #endif
 
 	// Set return error code
-	I callbackErr;
-	std::memcpy(&callbackErr, &out, sizeof(callbackErr));
-	return callbackErr;
+	ErrorCode code = static_cast<ErrorCode>(reinterpret_cast<PtrSize>(out));
+	return code;
 }
 
 //==============================================================================
@@ -135,7 +132,7 @@ Mutex::Mutex()
 		reinterpret_cast<pthread_mutex_t*>(malloc(sizeof(pthread_mutex_t)));
 	if(mtx == nullptr)
 	{
-		throw ANKI_EXCEPTION("Out of memory");
+		ANKI_LOGF("Out of memory");
 	}
 
 	m_impl = mtx;
@@ -145,7 +142,7 @@ Mutex::Mutex()
 	{
 		free(m_impl);
 		m_impl = nullptr;
-		throw ANKI_EXCEPTION("pthread_mutex_init() failed");
+		ANKI_LOGF("pthread_mutex_init() failed");
 	}
 }
 
@@ -167,7 +164,7 @@ void Mutex::lock()
 	I err = pthread_mutex_lock(mtx);
 	if(err)
 	{
-		throw ANKI_EXCEPTION("pthread_mutex_lock() failed");
+		ANKI_LOGF("pthread_mutex_lock() failed");
 	}
 }
 
@@ -188,7 +185,7 @@ void Mutex::unlock()
 	I err = pthread_mutex_unlock(mtx);
 	if(err)
 	{
-		throw ANKI_EXCEPTION("pthread_mutex_unlock() failed");
+		ANKI_LOGF("pthread_mutex_unlock() failed");
 	}
 }
 
@@ -203,7 +200,7 @@ ConditionVariable::ConditionVariable()
 		reinterpret_cast<pthread_cond_t*>(malloc(sizeof(pthread_cond_t)));
 	if(cond == nullptr)
 	{
-		throw ANKI_EXCEPTION("Out of memory");
+		ANKI_LOGF("Out of memory");
 	}
 
 	m_impl = cond;
@@ -213,7 +210,7 @@ ConditionVariable::ConditionVariable()
 	{
 		free(m_impl);
 		m_impl = nullptr;
-		throw ANKI_EXCEPTION("pthread_cond_init() failed");
+		ANKI_LOGF("pthread_cond_init() failed");
 	}
 }
 
@@ -242,51 +239,17 @@ void ConditionVariable::notifyAll()
 }
 
 //==============================================================================
-Bool ConditionVariable::wait(Mutex& amtx, F64 timeoutSeconds)
+void ConditionVariable::wait(Mutex& amtx)
 {
 	pthread_cond_t* cond = reinterpret_cast<pthread_cond_t*>(m_impl);
 	pthread_mutex_t* mtx = reinterpret_cast<pthread_mutex_t*>(amtx.m_impl);
 
-	Bool timeout = false;
-	I err = 0;
+	I err = pthread_cond_wait(cond, mtx);
 
-	if(timeoutSeconds == 0.0)
-	{
-		err = pthread_cond_wait(cond, mtx);
-	}
-	else
-	{
-		U64 ns = static_cast<U64>(timeoutSeconds * 1e+9);
-		struct timespec reltime;
-		reltime.tv_sec = ns / 1000000000;
-		reltime.tv_nsec = (ns % 1000000000);
-
-		struct timespec now;
-		clock_gettime(CLOCK_REALTIME, &now);
-
-		struct timespec abstime;
-		memset(&abstime, 0, sizeof(abstime));
-		abstime.tv_sec = now.tv_sec + reltime.tv_sec;
-		abstime.tv_nsec = now.tv_nsec + reltime.tv_nsec;
-		
-		err = pthread_cond_timedwait(cond, mtx, &abstime);
-	}
-
-	if(err == 0)
-	{
-		// Do nothing
-	}
-	else if(err == ETIMEDOUT)
-	{
-		timeout = true;
-	}
-	else
+	if(err)
 	{
-		throw ANKI_EXCEPTION("pthread_cond_wait() or pthread_cond_timedwait()"
-			" failed: %d", err);
+		ANKI_LOGF("pthread_cond_wait() failed: %d", err);
 	}
-
-	return timeout;
 }
 
 } // end namespace anki