Browse Source

Removing some exceptions

Panagiotis Christopoulos Charitos 11 years ago
parent
commit
5eec4cf570

+ 4 - 1
include/anki/gl/GlCommandBuffer.h

@@ -60,7 +60,10 @@ class GlCommandBufferInitHints
 	friend class GlCommandBuffer;
 
 private:
-	static const PtrSize m_maxChunkSize = 4 * 1024 * 1024; // 1MB
+	enum
+	{
+		MAX_CHUNK_SIZE = 4 * 1024 * 1024 // 1MB
+	};
 
 	PtrSize m_chunkSize = 1024;
 };

+ 13 - 3
include/anki/util/Allocator.h

@@ -86,9 +86,19 @@ public:
 	}
 
 	/// Constuctor that accepts a pool
-	explicit GenericPoolAllocator(const TPool& pool) noexcept
-	:	m_pool(pool)
-	{}
+	template<typename... TArgs>
+	explicit GenericPoolAllocator(
+		AllocAlignedCallback allocCb, void* allocCbUserData,
+		TArgs&&... args) noexcept
+	{
+		Error error = m_pool.create(
+			allocCb, allocCbUserData, std::forward<TArgs>(args)...);
+
+		if(error)
+		{
+			throw ANKI_EXCEPTION("Initialization failed");
+		}
+	}
 
 	/// Destructor
 	~GenericPoolAllocator()

+ 15 - 0
include/anki/util/Functions.h

@@ -174,6 +174,21 @@ constexpr typename std::underlying_type<TEnum>::type enumValue(TEnum val)
 	return static_cast<typename std::underlying_type<TEnum>::type>(val);
 }
 
+/// Construct an object
+template<typename T, typename... TArgs>
+void construct(T* p, TArgs&&... args)
+{
+	// Placement new
+	::new(reinterpret_cast<void*>(p)) T(std::forward<TArgs>(args)...);
+}
+
+/// Call destructor
+template<typename T>
+void destroy(T* p)
+{
+	p->~T();
+}
+
 /// @}
 
 } // end namespace anki

+ 32 - 32
include/anki/util/Memory.h

@@ -59,11 +59,6 @@ public:
 		*this = other;
 	}
 
-	/// The real constructor
-	/// @param allocCb The allocation function callback
-	/// @param allocCbUserData The user data to pass to the allocation function
-	HeapMemoryPool(AllocAlignedCallback allocCb, void* allocCbUserData);
-
 	/// Destroy
 	~HeapMemoryPool()
 	{
@@ -74,6 +69,11 @@ public:
 	/// other's pool to this instance as well
 	HeapMemoryPool& operator=(const HeapMemoryPool& other);
 
+	/// The real constructor
+	/// @param allocCb The allocation function callback
+	/// @param allocCbUserData The user data to pass to the allocation function
+	Error create(AllocAlignedCallback allocCb, void* allocCbUserData);
+
 	/// Check if two memory pools are the same one.
 	Bool operator==(const HeapMemoryPool& b) const noexcept
 	{
@@ -124,16 +124,6 @@ public:
 		*this = other;
 	}
 
-	/// Constructor with parameters
-	/// @param alloc The allocation function callback
-	/// @param allocUserData The user data to pass to the allocation function
-	/// @param size The size of the pool
-	/// @param alignmentBytes The maximum supported alignment for returned
-	///                       memory
-	StackMemoryPool(
-		AllocAlignedCallback alloc, void* allocUserData,
-		PtrSize size, PtrSize alignmentBytes = ANKI_SAFE_ALIGNMENT);
-
 	/// Destroy
 	~StackMemoryPool()
 	{
@@ -150,6 +140,16 @@ public:
 		return m_impl == b.m_impl;
 	}
 
+	/// Create with parameters
+	/// @param alloc The allocation function callback
+	/// @param allocUserData The user data to pass to the allocation function
+	/// @param size The size of the pool
+	/// @param alignmentBytes The maximum supported alignment for returned
+	///                       memory
+	Error create(
+		AllocAlignedCallback alloc, void* allocUserData,
+		PtrSize size, PtrSize alignmentBytes = ANKI_SAFE_ALIGNMENT);
+
 	/// Allocate aligned memory. The operation is thread safe
 	/// @param size The size to allocate
 	/// @param alignmentBytes The alignment of the returned address
@@ -227,6 +227,22 @@ public:
 		*this = other;
 	}
 
+	/// Destroy
+	~ChainMemoryPool()
+	{
+		clear();
+	}
+
+	/// Copy. It will not copy any data, what it will do is add visibility of
+	/// other's pool to this instance as well
+	ChainMemoryPool& operator=(const ChainMemoryPool& other);
+
+	/// Check if two memory pools are the same one.
+	Bool operator==(const ChainMemoryPool& b) const noexcept
+	{
+		return m_impl == b.m_impl;
+	}
+
 	/// Constructor with parameters
 	/// @param alloc The allocation function callback
 	/// @param allocUserData The user data to pass to the allocation function
@@ -237,7 +253,7 @@ public:
 	///                       the ammount of chunk size increase 
 	/// @param alignmentBytes The maximum supported alignment for returned
 	///                       memory
-	ChainMemoryPool(
+	Error create(
 		AllocAlignedCallback alloc, void* allocUserData,
 		PtrSize initialChunkSize,
 		PtrSize maxChunkSize,
@@ -246,22 +262,6 @@ public:
 		PtrSize chunkAllocStep = 2, 
 		PtrSize alignmentBytes = ANKI_SAFE_ALIGNMENT);
 
-	/// Destroy
-	~ChainMemoryPool()
-	{
-		clear();
-	}
-
-	/// Copy. It will not copy any data, what it will do is add visibility of
-	/// other's pool to this instance as well
-	ChainMemoryPool& operator=(const ChainMemoryPool& other);
-
-	/// Check if two memory pools are the same one.
-	Bool operator==(const ChainMemoryPool& b) const noexcept
-	{
-		return m_impl == b.m_impl;
-	}
-
 	/// Allocate memory. This operation is thread safe
 	/// @param size The size to allocate
 	/// @param alignmentBytes The alignment of the returned address

+ 1 - 1
src/core/App.cpp

@@ -37,7 +37,7 @@ App::App(const ConfigSet& config,
 	AllocAlignedCallback allocCb, void* allocCbUserData)
 :	m_allocCb(allocCb),
 	m_allocCbData(allocCbUserData),
-	m_heapAlloc(HeapMemoryPool(allocCb, allocCbUserData))
+	m_heapAlloc(allocCb, allocCbUserData)
 {
 	try
 	{

+ 3 - 3
src/gl/GlCommandBuffer.cpp

@@ -17,13 +17,13 @@ namespace anki {
 GlCommandBuffer::GlCommandBuffer(GlQueue* server, 
 	const GlCommandBufferInitHints& hints)
 :	m_server(server),
-	m_alloc(GlCommandBufferAllocator<GlCommand*>(ChainMemoryPool(
+	m_alloc(GlCommandBufferAllocator<GlCommand*>(
 		m_server->getAllocationCallback(),
 		m_server->getAllocationCallbackUserData(),
 		hints.m_chunkSize, 
-		hints.m_maxChunkSize, 
+		GlCommandBufferInitHints::MAX_CHUNK_SIZE, 
 		ChainMemoryPool::ChunkGrowMethod::ADD,
-		hints.m_chunkSize)))
+		hints.m_chunkSize))
 {
 	//std::cout << hints.m_chunkSize << std::endl;
 	ANKI_ASSERT(m_server);

+ 1 - 1
src/gl/GlDevice.cpp

@@ -14,7 +14,7 @@ GlDevice::GlDevice(
 	AllocAlignedCallback alloc, void* allocUserData,
 	const CString& cacheDir)
 {
-	m_alloc = HeapAllocator<U8>(HeapMemoryPool(alloc, allocUserData));
+	m_alloc = HeapAllocator<U8>(alloc, allocUserData);
 
 	// Allocate cache dir
 	auto len = cacheDir.getLength();

+ 3 - 4
src/resource/ResourceManager.cpp

@@ -21,10 +21,9 @@ namespace anki {
 //==============================================================================
 ResourceManager::ResourceManager(Initializer& init)
 :	m_gl(init.m_gl),
-	m_alloc(HeapMemoryPool(init.m_allocCallback, init.m_allocCallbackData)),
-	m_tmpAlloc(StackMemoryPool(
-		init.m_allocCallback, init.m_allocCallbackData, 
-		init.m_tempAllocatorMemorySize)),
+	m_alloc(init.m_allocCallback, init.m_allocCallbackData),
+	m_tmpAlloc(init.m_allocCallback, init.m_allocCallbackData, 
+		init.m_tempAllocatorMemorySize),
 	m_cacheDir(init.m_cacheDir, m_alloc),
 	m_dataDir(m_alloc),
 	m_shadersPrependedSource(m_alloc)

+ 2 - 3
src/scene/SceneGraph.cpp

@@ -79,9 +79,8 @@ SceneGraph::SceneGraph(AllocAlignedCallback allocCb, void* allocCbData,
 :	m_threadpool(threadpool),
 	m_resources(resources),
 	m_gl(&m_resources->_getGlDevice()),
-	m_alloc(StackMemoryPool(allocCb, allocCbData, ANKI_SCENE_ALLOCATOR_SIZE)),
-	m_frameAlloc(StackMemoryPool(allocCb, allocCbData, 
-		ANKI_SCENE_FRAME_ALLOCATOR_SIZE)),
+	m_alloc(allocCb, allocCbData, ANKI_SCENE_ALLOCATOR_SIZE),
+	m_frameAlloc(allocCb, allocCbData, ANKI_SCENE_FRAME_ALLOCATOR_SIZE),
 	m_nodes(m_alloc),
 	m_dict(10, DictionaryHasher(), DictionaryEqual(), m_alloc),
 	m_physics(),

+ 132 - 83
src/util/Memory.cpp

@@ -130,21 +130,6 @@ public:
 	}
 };
 
-//==============================================================================
-HeapMemoryPool::HeapMemoryPool(
-	AllocAlignedCallback allocCb, void* allocCbUserData)
-{
-	ANKI_ASSERT(allocCb != nullptr);
-
-	m_impl = static_cast<Implementation*>(allocCb(allocCbUserData, nullptr, 
-		sizeof(Implementation), alignof(Implementation)));
-
-	m_impl->m_refcount = 1;
-	m_impl->m_allocationsCount = 0;
-	m_impl->m_allocCb = allocCb;
-	m_impl->m_allocCbUserData = allocCbUserData;
-}
-
 //==============================================================================
 HeapMemoryPool& HeapMemoryPool::operator=(const HeapMemoryPool& other)
 {
@@ -159,6 +144,31 @@ HeapMemoryPool& HeapMemoryPool::operator=(const HeapMemoryPool& other)
 	return *this;
 }
 
+//==============================================================================
+Error HeapMemoryPool::create(
+	AllocAlignedCallback allocCb, void* allocCbUserData)
+{
+	ANKI_ASSERT(allocCb != nullptr);
+
+	Error error = ERROR_NONE;
+	m_impl = static_cast<Implementation*>(allocCb(allocCbUserData, nullptr, 
+		sizeof(Implementation), alignof(Implementation)));
+
+	if(m_impl)
+	{
+		m_impl->m_refcount = 1;
+		m_impl->m_allocationsCount = 0;
+		m_impl->m_allocCb = allocCb;
+		m_impl->m_allocCbUserData = allocCbUserData;
+	}
+	else
+	{
+		error = ERROR_OUT_OF_MEMORY;
+	}
+
+	return error;
+}
+
 //==============================================================================
 void HeapMemoryPool::clear()
 {
@@ -228,7 +238,7 @@ public:
 	static_assert(sizeof(MemoryBlockHeader) == sizeof(U32), "Size error");
 
 	/// Refcount
-	AtomicU32 m_refcount = {1};
+	AtomicU32 m_refcount;
 
 	/// User allocation function
 	AllocAlignedCallback m_allocCb;
@@ -243,27 +253,46 @@ public:
 	PtrSize m_headerSize;
 
 	/// Pre-allocated memory chunk
-	U8* m_memory = nullptr;
+	U8* m_memory;
 
 	/// Size of the pre-allocated memory chunk
-	PtrSize m_memsize = 0;
+	PtrSize m_memsize;
 
 	/// Points to the memory and more specifically to the top of the stack
-	Atomic<U8*> m_top = {nullptr};
+	Atomic<U8*> m_top;
+
+	AtomicU32 m_allocationsCount;
 
-	AtomicU32 m_allocationsCount = {0};
+	// Destroy
+	~Implementation()
+	{
+		if(m_memory != nullptr)
+		{
+#if ANKI_DEBUG
+			// Invalidate the memory
+			memset(m_memory, 0xCC, m_memsize);
+#endif
+			m_allocCb(m_allocCbUserData, m_memory, 0, 0);
+		}
+	}
 
 	// Construct
-	Implementation(AllocAlignedCallback allocCb, void* allocCbUserData,
+	Error create(AllocAlignedCallback allocCb, void* allocCbUserData,
 		PtrSize size, PtrSize alignmentBytes)
-	:	m_allocCb(allocCb),
-		m_allocCbUserData(allocCbUserData),
-		m_alignmentBytes(alignmentBytes), 
-		m_memsize(getAlignedRoundUp(alignmentBytes, size))
 	{
-		ANKI_ASSERT(m_allocCb);
-		ANKI_ASSERT(m_memsize > 0);
-		ANKI_ASSERT(m_alignmentBytes > 0);
+		ANKI_ASSERT(allocCb);
+		ANKI_ASSERT(size > 0);
+		ANKI_ASSERT(alignmentBytes > 0);
+
+		Error error = ERROR_NONE;
+
+		m_refcount = 1;
+		m_allocCb = allocCb;
+		m_allocCbUserData = allocCbUserData;
+		m_alignmentBytes = alignmentBytes;
+		m_memsize = getAlignedRoundUp(alignmentBytes, size);
+		m_allocationsCount = 0;
+
 		m_memory = (U8*)m_allocCb(
 			m_allocCbUserData, nullptr, m_memsize, m_alignmentBytes);
 
@@ -283,21 +312,10 @@ public:
 		}
 		else
 		{
-			throw ANKI_EXCEPTION("Failed to allocate memory");
+			error = ERROR_OUT_OF_MEMORY;
 		}
-	}
 
-	// Destroy
-	~Implementation()
-	{
-		if(m_memory != nullptr)
-		{
-#if ANKI_DEBUG
-			// Invalidate the memory
-			memset(m_memory, 0xCC, m_memsize);
-#endif
-			m_allocCb(m_allocCbUserData, m_memory, 0, 0);
-		}
+		return error;
 	}
 
 	PtrSize getTotalSize() const
@@ -418,18 +436,6 @@ public:
 	}
 };
 
-//==============================================================================
-StackMemoryPool::StackMemoryPool(
-	AllocAlignedCallback alloc, void* allocUserData,
-	PtrSize size, PtrSize alignmentBytes)
-{
-	m_impl = (Implementation*)alloc(allocUserData, nullptr, 
-		sizeof(Implementation), alignof(Implementation));
-	
-	::new((void*)m_impl) Implementation(
-		alloc, allocUserData, size, alignmentBytes);
-}
-
 //==============================================================================
 StackMemoryPool& StackMemoryPool::operator=(const StackMemoryPool& other)
 {
@@ -444,6 +450,30 @@ StackMemoryPool& StackMemoryPool::operator=(const StackMemoryPool& other)
 	return *this;
 }
 
+//==============================================================================
+Error StackMemoryPool::create(
+	AllocAlignedCallback alloc, void* allocUserData,
+	PtrSize size, PtrSize alignmentBytes)
+{
+	ANKI_ASSERT(m_impl == nullptr);
+
+	Error error = ERROR_NONE;
+	m_impl = static_cast<Implementation*>(alloc(allocUserData, nullptr, 
+		sizeof(Implementation), alignof(Implementation)));
+	
+	if(m_impl)
+	{
+		construct(m_impl);
+		error = m_impl->create(alloc, allocUserData, size, alignmentBytes);
+	}
+	else
+	{
+		error = ERROR_OUT_OF_MEMORY;
+	}
+
+	return error;
+}
+
 //==============================================================================
 void StackMemoryPool::clear()
 {
@@ -551,11 +581,6 @@ public:
 
 		/// Next chunk in the list
 		Chunk* m_next = nullptr;
-
-		Chunk(AllocAlignedCallback alloc, void* allocUserData, 
-			PtrSize size, PtrSize alignmentBytes)
-		:	m_pool(alloc, allocUserData, size, alignmentBytes)
-		{}
 	};
 
 	/// Refcount
@@ -706,20 +731,30 @@ public:
 		if(chunk)
 		{
 			// Construct it
-			::new((void*)chunk) Chunk(
+			construct(chunk);
+			Error error = chunk->m_pool.create(
 				m_allocCb, m_allocCbUserData, size, m_alignmentBytes);
 
-			// Register it
-			if(m_tailChunk)
+			if(!error)
 			{
-				m_tailChunk->m_next = chunk;
-				m_tailChunk = chunk;
+				// Register it
+				if(m_tailChunk)
+				{
+					m_tailChunk->m_next = chunk;
+					m_tailChunk = chunk;
+				}
+				else
+				{
+					ANKI_ASSERT(m_headChunk == nullptr);
+
+					m_headChunk = m_tailChunk = chunk;
+				}
 			}
 			else
 			{
-				ANKI_ASSERT(m_headChunk == nullptr);
-
-				m_headChunk = m_tailChunk = chunk;
+				destroy(chunk);
+				m_allocCb(m_allocCbUserData, chunk, 0, 0);
+				chunk = nullptr;
 			}
 		}
 		
@@ -865,7 +900,21 @@ public:
 };
 
 //==============================================================================
-ChainMemoryPool::ChainMemoryPool(
+ChainMemoryPool& ChainMemoryPool::operator=(const ChainMemoryPool& other)
+{
+	clear();
+
+	if(other.m_impl)
+	{
+		m_impl = other.m_impl;
+		++m_impl->m_refcount;
+	}
+
+	return *this;
+}
+
+//==============================================================================
+Error ChainMemoryPool::create(
 	AllocAlignedCallback alloc, 
 	void* allocUserData,
 	PtrSize initialChunkSize,
@@ -874,27 +923,27 @@ ChainMemoryPool::ChainMemoryPool(
 	PtrSize chunkAllocStep, 
 	PtrSize alignmentBytes)
 {
-	m_impl = (Implementation*)alloc(allocUserData, nullptr, 
-		sizeof(Implementation), alignof(Implementation));
+	ANKI_ASSERT(m_impl == nullptr);
 
-	::new((void*)m_impl) Implementation(
-		alloc, allocUserData,
-		initialChunkSize, maxChunkSize, chunkAllocStepMethod, chunkAllocStep,
-		alignmentBytes);
-}
-
-//==============================================================================
-ChainMemoryPool& ChainMemoryPool::operator=(const ChainMemoryPool& other)
-{
-	clear();
+	Error error = ERROR_NONE;
+	m_impl = static_cast<Implementation*>(alloc(allocUserData, nullptr, 
+		sizeof(Implementation), alignof(Implementation)));
 
-	if(other.m_impl)
+	if(m_impl)
 	{
-		m_impl = other.m_impl;
-		++m_impl->m_refcount;
+		construct(
+			m_impl,
+			alloc, allocUserData,
+			initialChunkSize, maxChunkSize, chunkAllocStepMethod, 
+			chunkAllocStep,
+			alignmentBytes);
+	}
+	else
+	{
+		error = ERROR_OUT_OF_MEMORY;
 	}
 
-	return *this;
+	return error;
 }
 
 //==============================================================================

+ 1 - 1
tests/Main.cpp

@@ -11,7 +11,7 @@ using namespace anki;
 
 int main(int argc, char** argv)
 {
-	HeapAllocator<U8> alloc(HeapMemoryPool(allocAligned, nullptr));
+	HeapAllocator<U8> alloc(allocAligned, nullptr);
 
 	// Call a few singletons to avoid memory leak confusion
 	LoggerSingleton::init(

+ 1 - 1
tests/resource/AsyncLoader.cpp

@@ -83,7 +83,7 @@ public:
 //==============================================================================
 ANKI_TEST(Resource, AsyncLoader)
 {
-	HeapAllocator<U8> alloc(HeapMemoryPool(allocAligned, nullptr));
+	HeapAllocator<U8> alloc(allocAligned, nullptr);
 
 	// Simple create destroy
 	{

+ 1 - 1
tests/resource/ResourceManager.cpp

@@ -17,7 +17,7 @@ ANKI_TEST(Resource, ResourceManager)
 	// Create
 	Config config;
 	
-	HeapAllocator<U8> alloc(HeapMemoryPool(allocAligned, nullptr));
+	HeapAllocator<U8> alloc(allocAligned, nullptr);
 
 	GlDevice* gl = alloc.newInstance<GlDevice>(
 		allocAligned, nullptr, "/tmp/");

+ 1 - 1
tests/script/LuaBinder.cpp

@@ -16,7 +16,7 @@ v3:setZ(0.1)
 
 ANKI_TEST(Script, LuaBinder)
 {
-	HeapAllocator<U8> alloc(HeapMemoryPool(allocAligned, nullptr));
+	HeapAllocator<U8> alloc(allocAligned, nullptr);
 	ScriptManager sm(alloc, nullptr);
 	Vec2 v2(2.0, 3.0);
 	Vec3 v3(1.1, 2.2, 3.3);

+ 3 - 4
tests/util/Allocator.cpp

@@ -14,8 +14,7 @@ ANKI_TEST(Allocators, StackAllocator)
 
 	// With simple string
 	{
-		StackAllocator<char, false> alloc(
-			StackMemoryPool(allocAligned, nullptr, 128));
+		StackAllocator<char, false> alloc(allocAligned, nullptr, 128);
 		typedef std::basic_string<char, std::char_traits<char>, 
 			StackAllocator<char, false>> Str;
 
@@ -28,8 +27,8 @@ ANKI_TEST(Allocators, StackAllocator)
 	// With vector
 	{
 		typedef StackAllocator<Foo, false> All;
-		All alloc(StackMemoryPool(allocAligned, nullptr, 
-			(sizeof(Foo) + 1) * 10, 1));
+		All alloc(allocAligned, nullptr, 
+			(sizeof(Foo) + 1) * 10, 1);
 		std::vector<Foo, All> vec(alloc);
 
 		vec.reserve(10);

+ 8 - 2
tests/util/Memory.cpp

@@ -42,10 +42,13 @@ ANKI_TEST(Memory, ChainMemoryPool)
 	// Basic test
 	{
 		const U size = 8;
-		ChainMemoryPool pool(
+		ChainMemoryPool pool;
+
+		Error error = pool.create(
 			allocAligned, nullptr,
 			size, size + 1, 
 			ChainMemoryPool::ChunkGrowMethod::MULTIPLY, 2, 1);
+		ANKI_TEST_EXPECT_EQ(error, ERROR_NONE);
 
 		void* mem = pool.allocate(5, 1);
 		ANKI_TEST_EXPECT_NEQ(mem, nullptr);
@@ -61,10 +64,13 @@ ANKI_TEST(Memory, ChainMemoryPool)
 	// Basic test 2
 	{
 		const U size = sizeof(PtrSize) + 10;
-		ChainMemoryPool pool(
+		ChainMemoryPool pool;
+		
+		Error error = pool.create(
 			allocAligned, nullptr,
 			size, size * 2, 
 			ChainMemoryPool::ChunkGrowMethod::MULTIPLY, 2, 1);
+		ANKI_TEST_EXPECT_EQ(error, ERROR_NONE);
 
 		void* mem = pool.allocate(size, 1);
 		ANKI_TEST_EXPECT_NEQ(mem, nullptr);

+ 1 - 1
tests/util/String.cpp

@@ -12,7 +12,7 @@ namespace anki {
 //==============================================================================
 ANKI_TEST(Util, String)
 {
-	HeapAllocator<U8> alloc(HeapMemoryPool(allocAligned, nullptr));
+	HeapAllocator<U8> alloc(allocAligned, nullptr);
 
 	// Copy
 	{