Browse Source

Finalizing the chain allocator & some GL renaming

Panagiotis Christopoulos Charitos 12 years ago
parent
commit
43ffa8ad16

+ 2 - 2
include/anki/gl/Ogl.h → include/anki/gl/Common.h

@@ -1,5 +1,5 @@
-#ifndef ANKI_GL_OGL_H
-#define ANKI_GL_OGL_H
+#ifndef ANKI_GL_COMMON_H
+#define ANKI_GL_COMMON_H
 
 
 #include "anki/Config.h"
 #include "anki/Config.h"
 
 

+ 1 - 1
include/anki/gl/Drawcall.h

@@ -1,7 +1,7 @@
 #ifndef ANKI_GL_DRAWCALL_H
 #ifndef ANKI_GL_DRAWCALL_H
 #define ANKI_GL_DRAWCALL_H
 #define ANKI_GL_DRAWCALL_H
 
 
-#include "anki/gl/Ogl.h"
+#include "anki/gl/Common.h"
 #include "anki/util/StdTypes.h"
 #include "anki/util/StdTypes.h"
 #include "anki/util/Array.h"
 #include "anki/util/Array.h"
 
 

+ 2 - 2
include/anki/gl/Gl.h

@@ -4,7 +4,7 @@
 #ifndef ANKI_GL_GL_H
 #ifndef ANKI_GL_GL_H
 #define ANKI_GL_GL_H
 #define ANKI_GL_GL_H
 
 
-#include "anki/gl/BufferObject.h"
+#include "anki/gl/GlBuffer.h"
 #include "anki/gl/Fbo.h"
 #include "anki/gl/Fbo.h"
 #include "anki/gl/GlException.h"
 #include "anki/gl/GlException.h"
 #include "anki/gl/GlState.h"
 #include "anki/gl/GlState.h"
@@ -14,6 +14,6 @@
 #include "anki/gl/Vao.h"
 #include "anki/gl/Vao.h"
 #include "anki/gl/Drawcall.h"
 #include "anki/gl/Drawcall.h"
 
 
-#include "anki/gl/Ogl.h"
+#include "anki/gl/Common.h"
 
 
 #endif
 #endif

+ 7 - 7
include/anki/gl/BufferObject.h → include/anki/gl/GlBuffer.h

@@ -1,5 +1,5 @@
-#ifndef ANKI_GL_BUFFER_OBJECT_H
-#define ANKI_GL_BUFFER_OBJECT_H
+#ifndef ANKI_GL_GL_BUFFER_H
+#define ANKI_GL_GL_BUFFER_H
 
 
 #include "anki/gl/GlObject.h"
 #include "anki/gl/GlObject.h"
 
 
@@ -10,7 +10,7 @@ namespace anki {
 	
 	
 /// A wrapper for OpenGL buffer objects (vertex arrays, texture buffers etc)
 /// A wrapper for OpenGL buffer objects (vertex arrays, texture buffers etc)
 /// to prevent us from making idiotic errors
 /// to prevent us from making idiotic errors
-class BufferObject: public GlObject
+class GlBuffer: public GlObject
 {
 {
 public:
 public:
 	typedef GlObject Base;
 	typedef GlObject Base;
@@ -19,24 +19,24 @@ public:
 	/// @{
 	/// @{
 
 
 	/// Default
 	/// Default
-	BufferObject()
+	GlBuffer()
 	{}
 	{}
 
 
 	/// Move
 	/// Move
-	BufferObject(BufferObject&& b)	
+	GlBuffer(GlBuffer&& b)	
 	{
 	{
 		*this = std::move(b);
 		*this = std::move(b);
 	}
 	}
 
 
 	/// It deletes the BO
 	/// It deletes the BO
-	~BufferObject()
+	~GlBuffer()
 	{
 	{
 		destroy();
 		destroy();
 	}
 	}
 	/// @}
 	/// @}
 
 
 	/// Move
 	/// Move
-	BufferObject& operator=(BufferObject&& b);
+	GlBuffer& operator=(GlBuffer&& b);
 
 
 	/// @name Accessors
 	/// @name Accessors
 	/// @{
 	/// @{

+ 1 - 1
include/anki/gl/GlObject.h

@@ -1,7 +1,7 @@
 #ifndef ANKI_GL_GL_OBJECT_H
 #ifndef ANKI_GL_GL_OBJECT_H
 #define ANKI_GL_GL_OBJECT_H
 #define ANKI_GL_GL_OBJECT_H
 
 
-#include "anki/gl/Ogl.h"
+#include "anki/gl/Common.h"
 #include "anki/gl/GlException.h"
 #include "anki/gl/GlException.h"
 #include "anki/Config.h"
 #include "anki/Config.h"
 #include "anki/util/NonCopyable.h"
 #include "anki/util/NonCopyable.h"

+ 1 - 1
include/anki/gl/GlState.h

@@ -2,7 +2,7 @@
 #define ANKI_GL_GL_STATE_H
 #define ANKI_GL_GL_STATE_H
 
 
 #include "anki/util/Singleton.h"
 #include "anki/util/Singleton.h"
-#include "anki/gl/Ogl.h"
+#include "anki/gl/Common.h"
 #include "anki/util/Assert.h"
 #include "anki/util/Assert.h"
 #include "anki/util/StdTypes.h"
 #include "anki/util/StdTypes.h"
 #include "anki/util/Array.h"
 #include "anki/util/Array.h"

+ 1 - 1
include/anki/gl/Texture.h

@@ -7,7 +7,7 @@
 #include "anki/util/Vector.h"
 #include "anki/util/Vector.h"
 #include "anki/util/StdTypes.h"
 #include "anki/util/StdTypes.h"
 #include "anki/util/NonCopyable.h"
 #include "anki/util/NonCopyable.h"
-#include "anki/gl/Ogl.h"
+#include "anki/gl/Common.h"
 #include <cstdlib>
 #include <cstdlib>
 #include <cstring>
 #include <cstring>
 #include <limits>
 #include <limits>

+ 4 - 4
include/anki/gl/Vao.h

@@ -7,7 +7,7 @@
 namespace anki {
 namespace anki {
 
 
 class ShaderProgramAttributeVariable;
 class ShaderProgramAttributeVariable;
-class BufferObject;
+class GlBuffer;
 
 
 /// @addtogroup OpenGL
 /// @addtogroup OpenGL
 /// @{
 /// @{
@@ -81,7 +81,7 @@ public:
 	/// @param offset Specifies a offset of the first component of the
 	/// @param offset Specifies a offset of the first component of the
 	///        first generic vertex attribute in the array
 	///        first generic vertex attribute in the array
 	void attachArrayBufferVbo(
 	void attachArrayBufferVbo(
-	    const BufferObject* vbo,
+	    const GlBuffer* vbo,
 	    const ShaderProgramAttributeVariable& attribVar,
 	    const ShaderProgramAttributeVariable& attribVar,
 	    const PtrSize size,
 	    const PtrSize size,
 	    const GLenum type,
 	    const GLenum type,
@@ -104,7 +104,7 @@ public:
 	/// @param pointer Specifies a offset of the first component of the
 	/// @param pointer Specifies a offset of the first component of the
 	///        first generic vertex attribute in the array
 	///        first generic vertex attribute in the array
 	void attachArrayBufferVbo(
 	void attachArrayBufferVbo(
-	    const BufferObject* vbo,
+	    const GlBuffer* vbo,
 	    const GLint attribVarLocation,
 	    const GLint attribVarLocation,
 	    const PtrSize size,
 	    const PtrSize size,
 	    const GLenum type,
 	    const GLenum type,
@@ -119,7 +119,7 @@ public:
 	}
 	}
 
 
 	/// Attach an element array buffer VBO
 	/// Attach an element array buffer VBO
-	void attachElementArrayBufferVbo(const BufferObject* vbo);
+	void attachElementArrayBufferVbo(const GlBuffer* vbo);
 
 
 	/// Bind it
 	/// Bind it
 	void bind() const
 	void bind() const

+ 2 - 2
include/anki/renderer/DebugDrawer.h

@@ -2,7 +2,7 @@
 #define ANKI_RENDERER_DEBUG_DRAWER_H
 #define ANKI_RENDERER_DEBUG_DRAWER_H
 
 
 #include "anki/Math.h"
 #include "anki/Math.h"
-#include "anki/gl/BufferObject.h"
+#include "anki/gl/GlBuffer.h"
 #include "anki/gl/Vao.h"
 #include "anki/gl/Vao.h"
 #include "anki/resource/Resource.h"
 #include "anki/resource/Resource.h"
 #include "anki/collision/CollisionShape.h"
 #include "anki/collision/CollisionShape.h"
@@ -64,7 +64,7 @@ private:
 
 
 	Array<Vertex, MAX_POINTS_PER_DRAW> clientVerts;
 	Array<Vertex, MAX_POINTS_PER_DRAW> clientVerts;
 
 
-	BufferObject vbo;
+	GlBuffer vbo;
 	Vao vao;
 	Vao vao;
 
 
 	/// This is a container of some precalculated spheres. Its a map that
 	/// This is a container of some precalculated spheres. Its a map that

+ 2 - 2
include/anki/renderer/Hdr.h

@@ -3,7 +3,7 @@
 
 
 #include "anki/renderer/RenderingPass.h"
 #include "anki/renderer/RenderingPass.h"
 #include "anki/gl/Fbo.h"
 #include "anki/gl/Fbo.h"
-#include "anki/gl/BufferObject.h"
+#include "anki/gl/GlBuffer.h"
 #include "anki/resource/TextureResource.h"
 #include "anki/resource/TextureResource.h"
 #include "anki/resource/ShaderProgramResource.h"
 #include "anki/resource/ShaderProgramResource.h"
 #include "anki/resource/Resource.h"
 #include "anki/resource/Resource.h"
@@ -69,7 +69,7 @@ private:
 	Timestamp parameterUpdateTimestamp = getGlobTimestamp();
 	Timestamp parameterUpdateTimestamp = getGlobTimestamp();
 	/// When the commonUbo got updated
 	/// When the commonUbo got updated
 	Timestamp commonUboUpdateTimestamp = getGlobTimestamp();
 	Timestamp commonUboUpdateTimestamp = getGlobTimestamp();
-	BufferObject commonUbo;
+	GlBuffer commonUbo;
 
 
 	void initFbo(Fbo& fbo, Texture& fai);
 	void initFbo(Fbo& fbo, Texture& fai);
 	void initInternal(const RendererInitializer& initializer);
 	void initInternal(const RendererInitializer& initializer);

+ 6 - 6
include/anki/renderer/Is.h

@@ -66,19 +66,19 @@ private:
 	PtrSize uboAlignment = MAX_PTR_SIZE; ///< Cache the value here
 	PtrSize uboAlignment = MAX_PTR_SIZE; ///< Cache the value here
 
 
 	/// Contains common data for all shader programs
 	/// Contains common data for all shader programs
-	BufferObject commonUbo;
+	GlBuffer commonUbo;
 
 
 	/// Track the updates of commonUbo
 	/// Track the updates of commonUbo
 	Timestamp commonUboUpdateTimestamp = getGlobTimestamp();
 	Timestamp commonUboUpdateTimestamp = getGlobTimestamp();
 
 
 	/// Contains all the lights
 	/// Contains all the lights
-	BufferObject lightsUbo;
+	GlBuffer lightsUbo;
 
 
 	/// Contains the number of lights per tile
 	/// Contains the number of lights per tile
-	BufferObject tilesBuffer;
+	GlBuffer tilesBuffer;
 
 
-	BufferObject pointLightIndicesBuffer;
-	BufferObject spotLightIndicesBuffer;
+	GlBuffer pointLightIndicesBuffer;
+	GlBuffer spotLightIndicesBuffer;
 	/// @}
 	/// @}
 
 
 	// Light shaders
 	// Light shaders
@@ -98,7 +98,7 @@ private:
 
 
 	/// @name For drawing a quad into the active framebuffer
 	/// @name For drawing a quad into the active framebuffer
 	/// @{
 	/// @{
-	BufferObject quadPositionsVbo; ///< The VBO for quad positions
+	GlBuffer quadPositionsVbo; ///< The VBO for quad positions
 	Vao quadVao; ///< This VAO is used everywhere except material stage
 	Vao quadVao; ///< This VAO is used everywhere except material stage
 	/// @}
 	/// @}
 
 

+ 1 - 1
include/anki/renderer/Lf.h

@@ -39,7 +39,7 @@ private:
 	TextureResourcePointer lensDirtTex;
 	TextureResourcePointer lensDirtTex;
 	U8 maxFlaresPerLight;
 	U8 maxFlaresPerLight;
 	U8 maxLightsWithFlares;
 	U8 maxLightsWithFlares;
-	BufferObject flareDataUbo;
+	GlBuffer flareDataUbo;
 	const ShaderProgramUniformBlock* ublock;
 	const ShaderProgramUniformBlock* ublock;
 	
 	
 
 

+ 1 - 1
include/anki/renderer/Renderer.h

@@ -266,7 +266,7 @@ private:
 
 
 	/// @name For drawing a quad into the active framebuffer
 	/// @name For drawing a quad into the active framebuffer
 	/// @{
 	/// @{
-	BufferObject quadPositionsVbo; ///< The VBO for quad positions
+	GlBuffer quadPositionsVbo; ///< The VBO for quad positions
 	Vao quadVao; ///< This VAO is used everywhere except material stage
 	Vao quadVao; ///< This VAO is used everywhere except material stage
 	/// @}
 	/// @}
 
 

+ 2 - 2
include/anki/renderer/Ssao.h

@@ -7,7 +7,7 @@
 #include "anki/resource/Resource.h"
 #include "anki/resource/Resource.h"
 #include "anki/gl/Fbo.h"
 #include "anki/gl/Fbo.h"
 #include "anki/gl/Texture.h"
 #include "anki/gl/Texture.h"
-#include "anki/gl/BufferObject.h"
+#include "anki/gl/GlBuffer.h"
 #include "anki/core/Timestamp.h"
 #include "anki/core/Timestamp.h"
 
 
 namespace anki {
 namespace anki {
@@ -49,7 +49,7 @@ private:
 	ShaderProgramResourcePointer hblurSProg;
 	ShaderProgramResourcePointer hblurSProg;
 	ShaderProgramResourcePointer vblurSProg;
 	ShaderProgramResourcePointer vblurSProg;
 	Timestamp commonUboUpdateTimestamp = getGlobTimestamp();
 	Timestamp commonUboUpdateTimestamp = getGlobTimestamp();
-	BufferObject commonUbo;
+	GlBuffer commonUbo;
 
 
 	static void createFbo(Fbo& fbo, Texture& fai, U width, U height);
 	static void createFbo(Fbo& fbo, Texture& fai, U width, U height);
 	void initInternal(const RendererInitializer& initializer);
 	void initInternal(const RendererInitializer& initializer);

+ 1 - 1
include/anki/renderer/Tiler.h

@@ -64,7 +64,7 @@ private:
 	Fbo fbo;
 	Fbo fbo;
 
 
 	/// PBO buffer that is used to read the data of fai asynchronously
 	/// PBO buffer that is used to read the data of fai asynchronously
-	BufferObject pbo;
+	GlBuffer pbo;
 
 
 	/// Main shader program
 	/// Main shader program
 	ShaderProgramResourcePointer prog;
 	ShaderProgramResourcePointer prog;

+ 0 - 1
include/anki/resource/Material.h

@@ -8,7 +8,6 @@
 #include "anki/util/Visitor.h"
 #include "anki/util/Visitor.h"
 #include "anki/util/Dictionary.h"
 #include "anki/util/Dictionary.h"
 #include "anki/util/NonCopyable.h"
 #include "anki/util/NonCopyable.h"
-#include "anki/gl/Ogl.h"
 #include <memory>
 #include <memory>
 
 
 namespace anki {
 namespace anki {

+ 4 - 4
include/anki/resource/Mesh.h

@@ -2,7 +2,7 @@
 #define ANKI_RESOURCE_MESH_H
 #define ANKI_RESOURCE_MESH_H
 
 
 #include "anki/Math.h"
 #include "anki/Math.h"
-#include "anki/gl/BufferObject.h"
+#include "anki/gl/GlBuffer.h"
 #include "anki/collision/Obb.h"
 #include "anki/collision/Obb.h"
 #include "anki/util/Vector.h"
 #include "anki/util/Vector.h"
 
 
@@ -85,7 +85,7 @@ public:
 
 
 	/// Get info on how to attach a VBO to a VAO
 	/// Get info on how to attach a VBO to a VAO
 	void getVboInfo(
 	void getVboInfo(
-		const VertexAttribute attrib, const BufferObject*& vbo,
+		const VertexAttribute attrib, const GlBuffer*& vbo,
 		U32& size, GLenum& type, U32& stride, U32& offset) const;
 		U32& size, GLenum& type, U32& stride, U32& offset) const;
 
 
 	/// Helper function for correct loading
 	/// Helper function for correct loading
@@ -110,8 +110,8 @@ protected:
 	U8 texChannelsCount;
 	U8 texChannelsCount;
 	Bool8 weights;
 	Bool8 weights;
 
 
-	BufferObject vbo;
-	BufferObject indicesVbo;
+	GlBuffer vbo;
+	GlBuffer indicesVbo;
 
 
 	/// Create the VBOs using the mesh data
 	/// Create the VBOs using the mesh data
 	void createVbos(const MeshLoader& loader);
 	void createVbos(const MeshLoader& loader);

+ 1 - 1
include/anki/scene/ParticleEmitter.h

@@ -220,7 +220,7 @@ private:
 	U32 aliveParticlesCountDraw = 0;
 	U32 aliveParticlesCountDraw = 0;
 
 
 	Vao vao; ///< Hold the VBO
 	Vao vao; ///< Hold the VBO
-	BufferObject vbo; ///< Hold the vertex data
+	GlBuffer vbo; ///< Hold the vertex data
 	SceneVector<F32> clientBuffer;
 	SceneVector<F32> clientBuffer;
 
 
 	U8 simulationType = UNDEFINED_SIMULATION;
 	U8 simulationType = UNDEFINED_SIMULATION;

+ 1 - 1
include/anki/scene/RenderComponent.h

@@ -4,7 +4,7 @@
 #include "anki/scene/Property.h"
 #include "anki/scene/Property.h"
 #include "anki/scene/Common.h"
 #include "anki/scene/Common.h"
 #include "anki/scene/SceneComponent.h"
 #include "anki/scene/SceneComponent.h"
-#include "anki/gl/BufferObject.h"
+#include "anki/gl/GlBuffer.h"
 #include "anki/resource/Material.h"
 #include "anki/resource/Material.h"
 #include "anki/resource/Model.h"
 #include "anki/resource/Model.h"
 
 

+ 60 - 51
include/anki/util/Allocator.h

@@ -6,7 +6,6 @@
 #include "anki/util/Memory.h"
 #include "anki/util/Memory.h"
 #include <cstddef> // For ptrdiff_t
 #include <cstddef> // For ptrdiff_t
 #include <utility> // For forward
 #include <utility> // For forward
-#include <memory> // For shared_ptr
 
 
 #define ANKI_DEBUG_ALLOCATORS ANKI_DEBUG
 #define ANKI_DEBUG_ALLOCATORS ANKI_DEBUG
 #define ANKI_PRINT_ALLOCATOR_MESSAGES 1
 #define ANKI_PRINT_ALLOCATOR_MESSAGES 1
@@ -230,26 +229,25 @@ inline bool operator!=(const HeapAllocator<T1>&, const AnotherAllocator&)
 	return true;
 	return true;
 }
 }
 
 
-/// Stack based allocator
+/// Pool based allocator
+///
+/// This is a template that accepts memory pools with a specific interface
 ///
 ///
 /// @tparam T The type
 /// @tparam T The type
 /// @tparam deallocationFlag If true then the allocator will try to deallocate
 /// @tparam deallocationFlag If true then the allocator will try to deallocate
-///                          the memory. This is extremely important to
+///                          the memory. It is extremely important to
 ///                          understand when it should be true. See notes
 ///                          understand when it should be true. See notes
-/// @tparam alignmentBytes Set the alighment in bytes
 ///
 ///
-/// @note The deallocationFlag can brake the allocator when the deallocations
-///       are not in the correct order. For example when deallocationFlag==true
-///       and the allocator is used in vector it is likely to fail.
+/// @note The deallocationFlag can brake the allocator when used with stack 
+///       pools and the deallocations are not in the correct order.
 ///
 ///
 /// @note Don't ever EVER remove the double copy constructor and the double
 /// @note Don't ever EVER remove the double copy constructor and the double
 ///       operator=. The compiler will create defaults
 ///       operator=. The compiler will create defaults
-template<typename T, Bool deallocationFlag = false,
-	U32 alignmentBytes = ANKI_SAFE_ALIGNMENT>
-class StackAllocator
+template<typename T, typename TPool, Bool deallocationFlag = false>
+class GenericPoolAllocator
 {
 {
-	template<typename U, Bool deallocationFlag_, U32 alignmentBytes_>
-	friend class StackAllocator;
+	template<typename U, typename TPool_, Bool deallocationFlag_>
+	friend class GenericPoolAllocator;
 
 
 public:
 public:
 	// Typedefs
 	// Typedefs
@@ -262,40 +260,43 @@ public:
 	typedef T value_type;
 	typedef T value_type;
 
 
 	/// Default constructor
 	/// Default constructor
-	StackAllocator() throw()
+	GenericPoolAllocator() throw()
 	{}
 	{}
+
 	/// Copy constructor
 	/// Copy constructor
-	StackAllocator(const StackAllocator& b) throw()
+	GenericPoolAllocator(const GenericPoolAllocator& b) throw()
 	{
 	{
 		*this = b;
 		*this = b;
 	}
 	}
+
 	/// Copy constructor
 	/// Copy constructor
 	template<typename U>
 	template<typename U>
-	StackAllocator(
-		const StackAllocator<U, deallocationFlag, alignmentBytes>& b) throw()
+	GenericPoolAllocator(const GenericPoolAllocator<
+		U, TPool, deallocationFlag>& b) throw()
 	{
 	{
 		*this = b;
 		*this = b;
 	}
 	}
-	/// Constuctor with size
-	StackAllocator(size_type size) throw()
-	{
-		mpool.reset(new StackMemoryPool(size, alignmentBytes));
-	}
+
+	/// Constuctor that accepts a pool
+	GenericPoolAllocator(const TPool& pool) throw()
+		: mpool(pool)
+	{}
 
 
 	/// Destructor
 	/// Destructor
-	~StackAllocator()
+	~GenericPoolAllocator()
 	{}
 	{}
 
 
 	/// Copy
 	/// Copy
-	StackAllocator& operator=(const StackAllocator& b)
+	GenericPoolAllocator& operator=(const GenericPoolAllocator& b)
 	{
 	{
 		mpool = b.mpool;
 		mpool = b.mpool;
 		return *this;
 		return *this;
 	}
 	}
+
 	/// Copy
 	/// Copy
 	template<typename U>
 	template<typename U>
-	StackAllocator& operator=(
-		const StackAllocator<U, deallocationFlag, alignmentBytes>& b)
+	GenericPoolAllocator& operator=(const GenericPoolAllocator<
+		U, TPool, deallocationFlag>& b)
 	{
 	{
 		mpool = b.mpool;
 		mpool = b.mpool;
 		return *this;
 		return *this;
@@ -306,6 +307,7 @@ public:
 	{
 	{
 		return &x;
 		return &x;
 	}
 	}
+
 	/// Get the const address of a const reference
 	/// Get the const address of a const reference
 	const_pointer address(const_reference x) const
 	const_pointer address(const_reference x) const
 	{
 	{
@@ -315,11 +317,10 @@ public:
 	/// Allocate memory
 	/// Allocate memory
 	pointer allocate(size_type n, const void* hint = 0)
 	pointer allocate(size_type n, const void* hint = 0)
 	{
 	{
-		ANKI_ASSERT(mpool != nullptr);
 		(void)hint;
 		(void)hint;
 		size_type size = n * sizeof(value_type);
 		size_type size = n * sizeof(value_type);
 		
 		
-		void* out = mpool->allocate(size);
+		void* out = mpool.allocate(size);
 
 
 		if(out != nullptr)
 		if(out != nullptr)
 		{
 		{
@@ -336,18 +337,17 @@ public:
 	/// Deallocate memory
 	/// Deallocate memory
 	void deallocate(void* p, size_type n)
 	void deallocate(void* p, size_type n)
 	{
 	{
-		ANKI_ASSERT(mpool != nullptr);
 		(void)p;
 		(void)p;
 		(void)n;
 		(void)n;
 
 
 		if(deallocationFlag)
 		if(deallocationFlag)
 		{
 		{
-			Bool ok = mpool->free(p);
+			Bool ok = mpool.free(p);
 
 
 			if(!ok)
 			if(!ok)
 			{
 			{
 				throw ANKI_EXCEPTION("Freeing wrong pointer. "
 				throw ANKI_EXCEPTION("Freeing wrong pointer. "
-					"The deallocations on StackAllocator should be in order");
+					"Pool's free returned false");
 			}
 			}
 		}
 		}
 	}
 	}
@@ -358,6 +358,7 @@ public:
 		// Placement new
 		// Placement new
 		new ((T*)p) T(val);
 		new ((T*)p) T(val);
 	}
 	}
+
 	/// Call constructor with many arguments
 	/// Call constructor with many arguments
 	template<typename U, typename... Args>
 	template<typename U, typename... Args>
 	void construct(U* p, Args&&... args)
 	void construct(U* p, Args&&... args)
@@ -371,6 +372,7 @@ public:
 	{
 	{
 		p->~T();
 		p->~T();
 	}
 	}
+
 	/// Call destructor
 	/// Call destructor
 	template<typename U>
 	template<typename U>
 	void destroy(U* p)
 	void destroy(U* p)
@@ -381,28 +383,25 @@ public:
 	/// Get the max allocation size
 	/// Get the max allocation size
 	size_type max_size() const
 	size_type max_size() const
 	{
 	{
-		ANKI_ASSERT(mpool != nullptr);
-		return mpool->getSize();
+		return mpool.getTotalSize();
 	}
 	}
 
 
 	/// A struct to rebind the allocator to another allocator of type U
 	/// A struct to rebind the allocator to another allocator of type U
 	template<typename U>
 	template<typename U>
 	struct rebind
 	struct rebind
 	{
 	{
-		typedef StackAllocator<U, deallocationFlag, alignmentBytes> other;
+		typedef GenericPoolAllocator<U, TPool, deallocationFlag> other;
 	};
 	};
 
 
 	/// Reinit the allocator. All existing allocated memory will be lost
 	/// Reinit the allocator. All existing allocated memory will be lost
 	void reset()
 	void reset()
 	{
 	{
-		ANKI_ASSERT(mpool != nullptr);
-		mpool->reset();
+		mpool.reset();
 	}
 	}
 
 
-	const StackMemoryPool& getMemoryPool() const
+	const TPool& getMemoryPool() const
 	{
 	{
-		ANKI_ASSERT(mpool != nullptr);
-		return *mpool;
+		return mpool;
 	}
 	}
 
 
 	/// Allocate a new object and call it's constructor
 	/// Allocate a new object and call it's constructor
@@ -460,47 +459,57 @@ public:
 	}
 	}
 
 
 private:
 private:
-	std::shared_ptr<StackMemoryPool> mpool;
+	TPool mpool;
 };
 };
 
 
 /// Another allocator of the same type can deallocate from this one
 /// Another allocator of the same type can deallocate from this one
-template<typename T1, typename T2, Bool deallocationFlag, U32 alignmentBytes>
+template<typename T1, typename T2, typename TPool, Bool deallocationFlag>
 inline bool operator==(
 inline bool operator==(
-	const StackAllocator<T1, deallocationFlag, alignmentBytes>&,
-	const StackAllocator<T2, deallocationFlag, alignmentBytes>&)
+	const GenericPoolAllocator<T1, TPool, deallocationFlag>&,
+	const GenericPoolAllocator<T2, TPool, deallocationFlag>&)
 {
 {
 	return true;
 	return true;
 }
 }
 
 
 /// Another allocator of the another type cannot deallocate from this one
 /// Another allocator of the another type cannot deallocate from this one
-template<typename T1, typename AnotherAllocator, Bool deallocationFlag,
-	U32 alignmentBytes>
+template<typename T1, typename AnotherAllocator, typename TPool, 
+	Bool deallocationFlag>
 inline bool operator==(
 inline bool operator==(
-	const StackAllocator<T1, deallocationFlag, alignmentBytes>&,
+	const GenericPoolAllocator<T1, TPool, deallocationFlag>&,
 	const AnotherAllocator&)
 	const AnotherAllocator&)
 {
 {
 	return false;
 	return false;
 }
 }
 
 
 /// Another allocator of the same type can deallocate from this one
 /// Another allocator of the same type can deallocate from this one
-template<typename T1, typename T2, Bool deallocationFlag, U32 alignmentBytes>
+template<typename T1, typename T2, typename TPool, Bool deallocationFlag>
 inline bool operator!=(
 inline bool operator!=(
-	const StackAllocator<T1, deallocationFlag, alignmentBytes>&,
-	const StackAllocator<T2, deallocationFlag, alignmentBytes>&)
+	const GenericPoolAllocator<T1, TPool, deallocationFlag>&,
+	const GenericPoolAllocator<T2, TPool, deallocationFlag>&)
 {
 {
 	return false;
 	return false;
 }
 }
 
 
 /// Another allocator of the another type cannot deallocate from this one
 /// Another allocator of the another type cannot deallocate from this one
-template<typename T1, typename AnotherAllocator, Bool deallocationFlag,
-	U32 alignmentBytes>
+template<typename T1, typename AnotherAllocator, typename TPool, 
+	Bool deallocationFlag>
 inline bool operator!=(
 inline bool operator!=(
-	const StackAllocator<T1, deallocationFlag, alignmentBytes>&,
+	const GenericPoolAllocator<T1, TPool, deallocationFlag>&,
 	const AnotherAllocator&)
 	const AnotherAllocator&)
 {
 {
 	return true;
 	return true;
 }
 }
 
 
+/// Allocator that uses a StackMemoryPool
+template<typename T, Bool deallocationFlag = false>
+using StackAllocator = 
+	GenericPoolAllocator<T, StackMemoryPool, deallocationFlag>;
+
+/// Allocator that uses a ChainMemoryPool
+template<typename T, Bool deallocationFlag = true>
+using ChainAllocator = 
+	GenericPoolAllocator<T, ChainMemoryPool, deallocationFlag>;
+
 /// @}
 /// @}
 /// @}
 /// @}
 
 

+ 65 - 71
include/anki/util/Memory.h

@@ -2,13 +2,7 @@
 #define ANKI_UTIL_MEMORY_H
 #define ANKI_UTIL_MEMORY_H
 
 
 #include "anki/util/StdTypes.h"
 #include "anki/util/StdTypes.h"
-#include "anki/util/Assert.h"
-#include "anki/util/NonCopyable.h"
-#include "anki/util/Thread.h"
-#include <atomic>
-#include <vector>
 #include <memory>
 #include <memory>
-#include <algorithm> // For the std::move
 
 
 namespace anki {
 namespace anki {
 
 
@@ -26,30 +20,38 @@ void freeAligned(void* ptr);
 /// Thread safe memory pool. It's a preallocated memory pool that is used for 
 /// Thread safe memory pool. It's a preallocated memory pool that is used for 
 /// memory allocations on top of that preallocated memory. It is mainly used by 
 /// memory allocations on top of that preallocated memory. It is mainly used by 
 /// fast stack allocators
 /// fast stack allocators
-class StackMemoryPool: public NonCopyable
+class StackMemoryPool
 {
 {
+	friend class ChainMemoryPool;
+
 public:
 public:
 	/// Default constructor
 	/// Default constructor
-	StackMemoryPool(PtrSize size, U32 alignmentBytes = ANKI_SAFE_ALIGNMENT);
+	StackMemoryPool()
+	{}
 
 
-	/// Move
-	StackMemoryPool(StackMemoryPool&& other)
+	/// Copy constructor. It's not copying any data
+	StackMemoryPool(const StackMemoryPool& other)
 	{
 	{
-		*this = std::move(other);
+		*this = other;
 	}
 	}
 
 
+	/// Constructor with parameters
+	StackMemoryPool(PtrSize size, U32 alignmentBytes = ANKI_SAFE_ALIGNMENT);
+
 	/// Destroy
 	/// Destroy
 	~StackMemoryPool();
 	~StackMemoryPool();
 
 
-	/// Move
-	StackMemoryPool& operator=(StackMemoryPool&& other);
-
-	/// Access the total size
-	PtrSize getSize() const
+	/// Copy. It will not copy any data, what it will do is add visibility of
+	/// other's pool to this instance as well
+	StackMemoryPool& operator=(const StackMemoryPool& other)
 	{
 	{
-		return memsize;
+		impl = other.impl;
+		return *this;
 	}
 	}
 
 
+	/// Access the total size
+	PtrSize getTotalSize() const;
+
 	/// Get the allocated size
 	/// Get the allocated size
 	PtrSize getAllocatedSize() const;
 	PtrSize getAllocatedSize() const;
 
 
@@ -60,7 +62,7 @@ public:
 	/// Free memory in StackMemoryPool. If the ptr is not the last allocation
 	/// Free memory in StackMemoryPool. If the ptr is not the last allocation
 	/// then nothing happens and the method returns false
 	/// then nothing happens and the method returns false
 	///
 	///
-	/// @param[in] ptr Memory block to deallocate
+	/// @param[in, out] ptr Memory block to deallocate
 	/// @return True if the deallocation actually happened and false otherwise
 	/// @return True if the deallocation actually happened and false otherwise
 	Bool free(void* ptr) throw();
 	Bool free(void* ptr) throw();
 
 
@@ -68,41 +70,58 @@ public:
 	void reset();
 	void reset();
 
 
 private:
 private:
-	/// Alignment of allocations
-	U32 alignmentBytes;
-
-	/// Pre-allocated memory chunk
-	U8* memory = nullptr;
+	// Forward
+	class Implementation;
 
 
-	/// Size of the pre-allocated memory chunk
-	PtrSize memsize = 0;
-
-	/// Points to the memory and more specifically to the top of the stack
-	std::atomic<U8*> top = {nullptr};
+	/// The actual implementation
+	std::shared_ptr<Implementation> impl;
 };
 };
 
 
 /// Chain memory pool. Almost similar to StackMemoryPool but more flexible and 
 /// Chain memory pool. Almost similar to StackMemoryPool but more flexible and 
 /// at the same time a bit slower.
 /// at the same time a bit slower.
-class ChainMemoryPool: public NonCopyable
+class ChainMemoryPool
 {
 {
 public:
 public:
-	/// Chunk allocation method
-	enum NextChunkAllocationMethod
+	/// Chunk allocation method. Defines the size a newely created has chunk 
+	/// compared to the last created
+	enum ChunkAllocationStepMethod
 	{
 	{
-		FIXED,
-		MULTIPLY,
-		ADD
+		FIXED, ///< All chunks have the same size
+		MULTIPLY, ///< Next chuck's size will be old_chuck_size * a_value
+		ADD ///< Next chuck's size will be old_chuck_size + a_value
 	};
 	};
 
 
-	/// Default constructor
+	/// Copy constructor. It's not copying any data
+	ChainMemoryPool(const ChainMemoryPool& other)
+	{
+		*this = other;
+	}
+
+	/// Constructor with parameters
+	/// @param initialChunkSize The size of the first chunk
+	/// @param maxChunkSize The size of the chunks cannot exceed that number
+	/// @param chunkAllocStepMethod How new chunks grow compared to the old ones
+	/// @param chunkAllocStep Used along with chunkAllocStepMethod and defines
+	///                       the ammount of chunk size increase 
+	/// @param alignmentBytes The standard alignment of the allocations
 	ChainMemoryPool(
 	ChainMemoryPool(
-		NextChunkAllocationMethod allocMethod, 
-		U32 allocMethodValue, 
+		U32 initialChunkSize,
+		U32 maxChunkSize,
+		ChunkAllocationStepMethod chunkAllocStepMethod = MULTIPLY, 
+		U32 chunkAllocStep = 2, 
 		U32 alignmentBytes = ANKI_SAFE_ALIGNMENT);
 		U32 alignmentBytes = ANKI_SAFE_ALIGNMENT);
 
 
 	/// Destroy
 	/// Destroy
 	~ChainMemoryPool();
 	~ChainMemoryPool();
 
 
+	/// 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)
+	{
+		impl = other.impl;
+		return *this;
+	}
+
 	/// Allocate memory. This operation is thread safe
 	/// Allocate memory. This operation is thread safe
 	/// @return The allocated memory or nullptr on failure
 	/// @return The allocated memory or nullptr on failure
 	void* allocate(PtrSize size) throw();
 	void* allocate(PtrSize size) throw();
@@ -114,42 +133,17 @@ public:
 	/// @return True if the deallocation actually happened and false otherwise
 	/// @return True if the deallocation actually happened and false otherwise
 	Bool free(void* ptr) throw();
 	Bool free(void* ptr) throw();
 
 
-private:
-	/// A chunk of memory
-	class Chunk
-	{
-	public:
-		StackMemoryPool pool;
-		std::atomic<U32> allocationsCount;
-
-		Chunk(PtrSize size, U32 alignmentBytes)
-			: pool(size, alignmentBytes), allocationsCount{0}
-		{}
-	};
-
-	/// Alignment of allocations
-	U32 alignmentBytes;
-
-	/// A list of chunks
-	std::vector<Chunk*> chunks;
-
-	/// Current chunk to allocate from
-	Chunk* crntChunk = nullptr;
-
-	/// Fast thread locking
-	SpinLock lock;
+	/// @name Methods used for debugging
+	/// @{
+	PtrSize getChunksCount() const;
+	/// @}
 
 
-	/// Chunk allocation method value
-	U32 chAllocMethodValue;
-
-	/// Chunk allocation method
-	U8 chAllocMethod;
-
-	/// Allocate memory from a chunk
-	void* allocateFromChunk(Chunk* ch, PtrSize size) throw();
+private:
+	// Forward
+	class Implementation;
 
 
-	/// Create a new chunk
-	Chunk* createNewChunk(PtrSize minSize) throw();
+	/// The actual implementation
+	std::shared_ptr<Implementation> impl;
 };
 };
 
 
 /// @}
 /// @}

+ 0 - 2
src/gl/CMakeLists.txt

@@ -1,6 +1,4 @@
 FILE(GLOB_RECURSE ANKI_GL_SOURCES *.cpp)
 FILE(GLOB_RECURSE ANKI_GL_SOURCES *.cpp)
 FILE(GLOB_RECURSE ANKI_GL_HEADERS *.h)
 FILE(GLOB_RECURSE ANKI_GL_HEADERS *.h)
 
 
-#INCLUDE_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/BufferObjects")
-
 ADD_LIBRARY(ankigl ${ANKI_GL_SOURCES} ${ANKI_GL_HEADERS})
 ADD_LIBRARY(ankigl ${ANKI_GL_SOURCES} ${ANKI_GL_HEADERS})

+ 11 - 11
src/gl/BufferObject.cpp → src/gl/GlBuffer.cpp

@@ -1,5 +1,5 @@
 #include <cstring>
 #include <cstring>
-#include "anki/gl/BufferObject.h"
+#include "anki/gl/GlBuffer.h"
 #include "anki/gl/GlException.h"
 #include "anki/gl/GlException.h"
 #include "anki/util/Exception.h"
 #include "anki/util/Exception.h"
 #include "anki/core/Logger.h"
 #include "anki/core/Logger.h"
@@ -16,11 +16,11 @@ namespace anki {
 #define USE_BUFFER_DATA_ON_WRITE 1
 #define USE_BUFFER_DATA_ON_WRITE 1
 
 
 //==============================================================================
 //==============================================================================
-// BufferObject                                                                =
+// GlBuffer                                                                    =
 //==============================================================================
 //==============================================================================
 
 
 //==============================================================================
 //==============================================================================
-BufferObject& BufferObject::operator=(BufferObject&& b)
+GlBuffer& GlBuffer::operator=(GlBuffer&& b)
 {
 {
 	destroy();
 	destroy();
 	Base::operator=(std::forward<Base>(b));
 	Base::operator=(std::forward<Base>(b));
@@ -34,7 +34,7 @@ BufferObject& BufferObject::operator=(BufferObject&& b)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void BufferObject::destroy()
+void GlBuffer::destroy()
 {
 {
 	if(isCreated())
 	if(isCreated())
 	{
 	{
@@ -45,7 +45,7 @@ void BufferObject::destroy()
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void BufferObject::create(GLenum target_, U32 sizeInBytes_,
+void GlBuffer::create(GLenum target_, U32 sizeInBytes_,
 	const void* dataPtr, GLenum usage_)
 	const void* dataPtr, GLenum usage_)
 {
 {
 	ANKI_ASSERT(!isCreated());
 	ANKI_ASSERT(!isCreated());
@@ -94,7 +94,7 @@ void BufferObject::create(GLenum target_, U32 sizeInBytes_,
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void* BufferObject::map(U32 offset, U32 length, GLuint flags)
+void* GlBuffer::map(U32 offset, U32 length, GLuint flags)
 {
 {
 	// XXX Remove this workaround
 	// XXX Remove this workaround
 #if ANKI_GL == ANKI_GL_ES
 #if ANKI_GL == ANKI_GL_ES
@@ -120,7 +120,7 @@ void* BufferObject::map(U32 offset, U32 length, GLuint flags)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void BufferObject::unmap()
+void GlBuffer::unmap()
 {
 {
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());
 #if ANKI_DEBUG
 #if ANKI_DEBUG
@@ -134,7 +134,7 @@ void BufferObject::unmap()
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void BufferObject::write(void* buff, U32 offset, U32 size)
+void GlBuffer::write(void* buff, U32 offset, U32 size)
 {
 {
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(usage != GL_STATIC_DRAW);
 	ANKI_ASSERT(usage != GL_STATIC_DRAW);
@@ -154,7 +154,7 @@ void BufferObject::write(void* buff, U32 offset, U32 size)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void BufferObject::read(void* outBuff, U32 offset, U32 size)
+void GlBuffer::read(void* outBuff, U32 offset, U32 size)
 {
 {
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(usage != GL_STATIC_DRAW);
 	ANKI_ASSERT(usage != GL_STATIC_DRAW);
@@ -167,7 +167,7 @@ void BufferObject::read(void* outBuff, U32 offset, U32 size)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void BufferObject::setBinding(GLuint binding) const
+void GlBuffer::setBinding(GLuint binding) const
 {
 {
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());
 	glBindBufferBase(target, binding, getGlId());
 	glBindBufferBase(target, binding, getGlId());
@@ -175,7 +175,7 @@ void BufferObject::setBinding(GLuint binding) const
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void BufferObject::setBindingRange(
+void GlBuffer::setBindingRange(
 	GLuint binding, PtrSize offset, PtrSize size) const
 	GLuint binding, PtrSize offset, PtrSize size) const
 {
 {
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());

+ 4 - 4
src/gl/Vao.cpp

@@ -1,5 +1,5 @@
 #include "anki/gl/Vao.h"
 #include "anki/gl/Vao.h"
-#include "anki/gl/BufferObject.h"
+#include "anki/gl/GlBuffer.h"
 #include "anki/util/Exception.h"
 #include "anki/util/Exception.h"
 #include "anki/gl/ShaderProgram.h"
 #include "anki/gl/ShaderProgram.h"
 #include "anki/core/Logger.h"
 #include "anki/core/Logger.h"
@@ -25,7 +25,7 @@ void Vao::destroy()
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Vao::attachArrayBufferVbo(const BufferObject* vbo, 
+void Vao::attachArrayBufferVbo(const GlBuffer* vbo, 
 	const GLint attribVarLocation,
 	const GLint attribVarLocation,
 	const PtrSize size, const GLenum type, const Bool normalized, 
 	const PtrSize size, const GLenum type, const Bool normalized, 
 	const PtrSize stride, const PtrSize offset)
 	const PtrSize stride, const PtrSize offset)
@@ -50,7 +50,7 @@ void Vao::attachArrayBufferVbo(const BufferObject* vbo,
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Vao::attachArrayBufferVbo(const BufferObject* vbo,
+void Vao::attachArrayBufferVbo(const GlBuffer* vbo,
 	const ShaderProgramAttributeVariable& attribVar,
 	const ShaderProgramAttributeVariable& attribVar,
 	const PtrSize size, const GLenum type, const Bool normalized, 
 	const PtrSize size, const GLenum type, const Bool normalized, 
 	const PtrSize stride, const PtrSize offset)
 	const PtrSize stride, const PtrSize offset)
@@ -60,7 +60,7 @@ void Vao::attachArrayBufferVbo(const BufferObject* vbo,
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Vao::attachElementArrayBufferVbo(const BufferObject* vbo)
+void Vao::attachElementArrayBufferVbo(const GlBuffer* vbo)
 {
 {
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());
 	checkNonSharable();
 	checkNonSharable();

+ 1 - 1
src/renderer/Is.cpp

@@ -516,7 +516,7 @@ void Is::initInternal(const RendererInitializer& initializer)
 	// Create UBOs
 	// Create UBOs
 	//
 	//
 
 
-	uboAlignment = BufferObject::getUniformBufferOffsetAlignment();
+	uboAlignment = GlBuffer::getUniformBufferOffsetAlignment();
 
 
 	commonUbo.create(GL_UNIFORM_BUFFER, sizeof(shader::CommonUniforms), 
 	commonUbo.create(GL_UNIFORM_BUFFER, sizeof(shader::CommonUniforms), 
 		nullptr, GL_DYNAMIC_DRAW);
 		nullptr, GL_DYNAMIC_DRAW);

+ 1 - 1
src/resource/Mesh.cpp

@@ -120,7 +120,7 @@ void Mesh::createVbos(const MeshLoader& loader)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Mesh::getVboInfo(const VertexAttribute attrib, const BufferObject*& v, 
+void Mesh::getVboInfo(const VertexAttribute attrib, const GlBuffer*& v, 
 	U32& size, GLenum& type, U32& stride, U32& offset) const
 	U32& size, GLenum& type, U32& stride, U32& offset) const
 {
 {
 	stride = calcVertexSize();
 	stride = calcVertexSize();

+ 1 - 1
src/resource/Model.cpp

@@ -36,7 +36,7 @@ void ModelPatchBase::createVao(const ShaderProgram& prog,
 {
 {
 	vao.create();
 	vao.create();
 
 
-	const BufferObject* vbo;
+	const GlBuffer* vbo;
 	U32 size;
 	U32 size;
 	GLenum type;
 	GLenum type;
 	U32 stride;
 	U32 stride;

+ 409 - 188
src/util/Memory.cpp

@@ -1,8 +1,10 @@
 #include "anki/util/Memory.h"
 #include "anki/util/Memory.h"
-#include "anki/util/Assert.h"
 #include "anki/util/Exception.h"
 #include "anki/util/Exception.h"
 #include "anki/util/Functions.h"
 #include "anki/util/Functions.h"
-#include <limits>
+#include "anki/util/Assert.h"
+#include "anki/util/NonCopyable.h"
+#include "anki/util/Thread.h"
+#include "anki/util/Vector.h"
 #include <cstdlib>
 #include <cstdlib>
 #include <cstring>
 #include <cstring>
 
 
@@ -68,279 +70,498 @@ void freeAligned(void* ptr)
 //==============================================================================
 //==============================================================================
 
 
 //==============================================================================
 //==============================================================================
-struct MemoryBlockHeader
+class StackMemoryPool::Implementation: public NonCopyable
 {
 {
-	U32 size;
-};
+public:
+	/// The header of each allocation
+	struct MemoryBlockHeader
+	{
+		U32 size;
+	};
 
 
-//==============================================================================
-StackMemoryPool::StackMemoryPool(PtrSize size, U32 alignmentBytes_)
-	:	alignmentBytes(alignmentBytes_), 
-		memsize(getAlignedRoundUp(alignmentBytes, size))
-{
-	ANKI_ASSERT(memsize > 0);
-	memory = (U8*)mallocAligned(memsize, alignmentBytes);
+	/// Alignment of allocations
+	U32 alignmentBytes;
 
 
-	if(memory != nullptr)
+	/// Pre-allocated memory chunk
+	U8* memory = nullptr;
+
+	/// Size of the pre-allocated memory chunk
+	PtrSize memsize = 0;
+
+	/// Points to the memory and more specifically to the top of the stack
+	std::atomic<U8*> top = {nullptr};
+
+	// Construct
+	Implementation(PtrSize size, U32 alignmentBytes_)
+		:	alignmentBytes(alignmentBytes_), 
+			memsize(getAlignedRoundUp(alignmentBytes, size))
 	{
 	{
-		// Align allocated memory
-		top = memory;
+		ANKI_ASSERT(memsize > 0);
+		memory = (U8*)mallocAligned(memsize, alignmentBytes);
+
+		if(memory != nullptr)
+		{
+			// Align allocated memory
+			top = memory;
+		}
+		else
+		{
+			throw ANKI_EXCEPTION("Failed to allocate memory");
+		}
 	}
 	}
-	else
+
+	// Destroy
+	~Implementation()
 	{
 	{
-		throw ANKI_EXCEPTION("Failed to allocate memory");
+		if(memory != nullptr)
+		{
+			freeAligned(memory);
+		}
 	}
 	}
-}
 
 
-//==============================================================================
-StackMemoryPool::~StackMemoryPool()
-{
-	if(memory != nullptr)
+	PtrSize getTotalSize() const
 	{
 	{
-		freeAligned(memory);
+		return memsize;
 	}
 	}
-}
 
 
-//==============================================================================
-StackMemoryPool& StackMemoryPool::operator=(StackMemoryPool&& other)
-{
-	if(memory != nullptr)
+	PtrSize getAllocatedSize() const
 	{
 	{
-		freeAligned(memory);
+		ANKI_ASSERT(memory != nullptr);
+		return top.load() - memory;
 	}
 	}
 
 
-	memory = other.memory;
-	memsize = other.memsize;
-	alignmentBytes = other.alignmentBytes;
-	top.store(other.top.load());
-
-	other.memory = nullptr;
-	other.memsize = 0;
-	other.top = nullptr;
-
-	return *this;
-}
+	const void* getBaseAddress() const
+	{
+		ANKI_ASSERT(memory != nullptr);
+		return memory;
+	}
 
 
-//==============================================================================
-PtrSize StackMemoryPool::getAllocatedSize() const
-{
-	return top.load() - memory;
-}
+	/// Allocate
+	void* allocate(PtrSize size_) throw()
+	{
+		// memory is nullptr if moved
+		ANKI_ASSERT(memory != nullptr);
 
 
-//==============================================================================
-void* StackMemoryPool::allocate(PtrSize size_) throw()
-{
-	// memory is nullptr if moved
-	ANKI_ASSERT(memory != nullptr);
+		PtrSize headerSize = 
+			getAlignedRoundUp(alignmentBytes, sizeof(MemoryBlockHeader));
+		PtrSize size = 
+			getAlignedRoundUp(alignmentBytes, size_ + headerSize);
 
 
-	PtrSize headerSize = 
-		getAlignedRoundUp(alignmentBytes, sizeof(MemoryBlockHeader));
-	PtrSize size = 
-		getAlignedRoundUp(alignmentBytes, size_ + headerSize);
+		ANKI_ASSERT(size < MAX_U32 && "Too big allocation");
 
 
-	ANKI_ASSERT(size < MAX_U32 && "Too big allocation");
+		U8* out = top.fetch_add(size);
 
 
-	U8* out = top.fetch_add(size);
+		if(out + size <= memory + memsize)
+		{
+			// Write the block header
+			((MemoryBlockHeader*)out)->size = size;
 
 
-	if(out + size <= memory + memsize)
-	{
-		// Write the block header
-		((MemoryBlockHeader*)out)->size = size;
+			// Set the correct output
+			out += headerSize;
 
 
-		// Set the correct output
-		out += headerSize;
+			// Check alignment
+			ANKI_ASSERT(isAligned(alignmentBytes, out));
+		}
+		else
+		{
+			// Error
+			out = nullptr;
+		}
 
 
-		// Check alignment
-		ANKI_ASSERT(isAligned(alignmentBytes, out));
-	}
-	else
-	{
-		// Error
-		out = nullptr;
+		return out;
 	}
 	}
 
 
-	return out;
-}
-
-//==============================================================================
-Bool StackMemoryPool::free(void* ptr) throw()
-{
-	// ptr shouldn't be null or not aligned. If not aligned it was not 
-	// allocated by this class
-	ANKI_ASSERT(ptr != nullptr && isAligned(alignmentBytes, ptr));
+	/// Free
+	Bool free(void* ptr) throw()
+	{
+		// ptr shouldn't be null or not aligned. If not aligned it was not 
+		// allocated by this class
+		ANKI_ASSERT(ptr != nullptr && isAligned(alignmentBytes, ptr));
 
 
-	// memory is nullptr if moved
-	ANKI_ASSERT(memory != nullptr);
+		// memory is nullptr if moved
+		ANKI_ASSERT(memory != nullptr);
 
 
-	// Correct the p
-	PtrSize headerSize = 
-		getAlignedRoundUp(alignmentBytes, sizeof(MemoryBlockHeader));
-	U8* realptr = (U8*)ptr - headerSize;
+		// Correct the p
+		PtrSize headerSize = 
+			getAlignedRoundUp(alignmentBytes, sizeof(MemoryBlockHeader));
+		U8* realptr = (U8*)ptr - headerSize;
 
 
-	// realptr should be inside the pool's preallocated memory
-	ANKI_ASSERT(realptr >= memory);
+		// realptr should be inside the pool's preallocated memory
+		ANKI_ASSERT(realptr >= memory);
 
 
-	// Get block size
-	U32 size = ((MemoryBlockHeader*)realptr)->size;
+		// Get block size
+		U32 size = ((MemoryBlockHeader*)realptr)->size;
 
 
-	// Check if the size is ok
-	ANKI_ASSERT(realptr + size <= memory + memsize);
+		// Check if the size is ok
+		ANKI_ASSERT(realptr + size <= memory + memsize);
 
 
-	// Atomic stuff
-	U8* expected = realptr + size;
-	U8* desired = realptr;
+		// Atomic stuff
+		U8* expected = realptr + size;
+		U8* desired = realptr;
 
 
-	// if(top == expected) {
-	//     top = desired;
-	//     exchange = true;
-	// } else {
-	//     expected = top;
-	//     exchange = false;
-	// }
-	Bool exchange = top.compare_exchange_strong(expected, desired);
+		// if(top == expected) {
+		//     top = desired;
+		//     exchange = true;
+		// } else {
+		//     expected = top;
+		//     exchange = false;
+		// }
+		Bool exchange = top.compare_exchange_strong(expected, desired);
 
 
-	return exchange;
-}
+		return exchange;
+	}
 
 
-//==============================================================================
-void StackMemoryPool::reset()
-{
-	// memory is nullptr if moved
-	ANKI_ASSERT(memory != nullptr);
+	/// Reset
+	void reset()
+	{
+		// memory is nullptr if moved
+		ANKI_ASSERT(memory != nullptr);
 
 
 #if ANKI_DEBUG
 #if ANKI_DEBUG
-	// Invalidate the memory
-	memset(memory, 0xCC, memsize);
+		// Invalidate the memory
+		memset(memory, 0xCC, memsize);
 #endif
 #endif
 
 
-	top = memory;
-}
+		top = memory;
+	}
+};
 
 
 //==============================================================================
 //==============================================================================
-// ChainMemoryPool                                                             =
-//==============================================================================
+StackMemoryPool::StackMemoryPool(PtrSize size, U32 alignmentBytes)
+{
+	impl.reset(new Implementation(size, alignmentBytes));
+}
 
 
 //==============================================================================
 //==============================================================================
-ChainMemoryPool::ChainMemoryPool(
-	NextChunkAllocationMethod allocMethod, 
-	U32 allocMethodValue, 
-	U32 alignmentBytes_)
-	:	alignmentBytes(alignmentBytes_), 
-		chAllocMethodValue(allocMethodValue),
-		chAllocMethod(allocMethod)
+StackMemoryPool::~StackMemoryPool()
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
-ChainMemoryPool::~ChainMemoryPool()
+PtrSize StackMemoryPool::getTotalSize() const
 {
 {
-	// TODO
+	ANKI_ASSERT(impl.get() != nullptr);
+	return impl->getTotalSize();
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void* ChainMemoryPool::allocateFromChunk(Chunk* ch, PtrSize size) throw()
+PtrSize StackMemoryPool::getAllocatedSize() const
 {
 {
-	ANKI_ASSERT(ch);
-	void* mem = ch->pool.allocate(size);
+	ANKI_ASSERT(impl.get() != nullptr);
+	return impl->getAllocatedSize();
+}
 
 
-	if(mem)
-	{
-		++ch->allocationsCount;
-	}
+//==============================================================================
+void* StackMemoryPool::allocate(PtrSize size) throw()
+{
+	ANKI_ASSERT(impl.get() != nullptr);
+	return impl->allocate(size);
+}
 
 
-	return mem;
+//==============================================================================
+Bool StackMemoryPool::free(void* ptr) throw()
+{
+	ANKI_ASSERT(impl.get() != nullptr);
+	return impl->free(ptr);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-ChainMemoryPool::Chunk* ChainMemoryPool::createNewChunk(PtrSize size) throw()
+void StackMemoryPool::reset()
 {
 {
-	//
-	// Calculate preferred size
-	//
-	
-	// Get the size of the next chunk
-	PtrSize crntMaxSize;
-	if(chAllocMethod == FIXED)
+	ANKI_ASSERT(impl.get() != nullptr);
+	impl->reset();
+}
+
+//==============================================================================
+// ChainMemoryPool                                                             =
+//==============================================================================
+
+//==============================================================================
+class ChainMemoryPool::Implementation: public NonCopyable
+{
+public:
+	/// A chunk of memory
+	class Chunk
 	{
 	{
-		crntMaxSize = chAllocMethodValue;
+	public:
+		StackMemoryPool::Implementation pool;
+		U32 allocationsCount;
+
+		Chunk(PtrSize size, U32 alignmentBytes)
+			: pool(size, alignmentBytes), allocationsCount(0)
+		{}
+	};
+
+	/// Alignment of allocations
+	U32 alignmentBytes;
+
+	/// A list of chunks
+	Vector<Chunk*> chunks;
+
+	/// Current chunk to allocate from
+	Chunk* crntChunk = nullptr;
+
+	/// Fast thread locking
+	SpinLock lock;
+
+	/// Chunk first chunk size
+	U32 initSize;
+
+	/// Chunk max size
+	U32 maxSize;
+
+	/// Chunk allocation method value
+	U32 step;
+
+	/// Chunk allocation method
+	U8 method;
+
+	/// Construct
+	Implementation(
+		U32 initialChunkSize,
+		U32 maxChunkSize,
+		ChunkAllocationStepMethod chunkAllocStepMethod, 
+		U32 chunkAllocStep, 
+		U32 alignmentBytes_)
+		:	alignmentBytes(alignmentBytes_), 
+			initSize(initialChunkSize),
+			maxSize(maxChunkSize),
+			step(chunkAllocStep),
+			method(chunkAllocStepMethod)
+	{
+		// Initial size should be > 0
+		ANKI_ASSERT(initSize > 0);
+
+		// On fixed step should be 0
+		ANKI_ASSERT(!(method == FIXED && step != 0));
+
+		// On fixed initial size is the same as the max
+		ANKI_ASSERT(!(method == FIXED && initSize != maxSize));
+
+		// On add and mul the max size should be greater than initial
+		ANKI_ASSERT(!(
+			(method == ADD || method == MULTIPLY) && initSize < maxSize));
 	}
 	}
-	else
+
+	/// Destroy
+	~Implementation()
+	{
+		for(Chunk* ch : chunks)
+		{
+			ANKI_ASSERT(ch);
+			delete ch;
+		}
+	}
+
+	/// Create a new chunk
+	Chunk* createNewChunk(PtrSize size) throw()
 	{
 	{
-		// Get the size of the previous max chunk
-		crntMaxSize = 0;
-		for(Chunk* c : chunks)
+		ANKI_ASSERT(size <= maxSize && "To big chunk");
+		//
+		// Calculate preferred size
+		//
+		
+		// Get the size of the next chunk
+		PtrSize crntMaxSize;
+		if(method == FIXED)
 		{
 		{
-			if(c)
+			crntMaxSize = initSize;
+		}
+		else
+		{
+			// Get the size of the previous max chunk
+			if(chunks.size() > 0)
 			{
 			{
-				PtrSize poolSize = c->pool.getSize();
-				crntMaxSize = std::max(crntMaxSize, poolSize);
+				// Get the size of previous
+				crntMaxSize = chunks.back()->pool.getTotalSize();
+
+				// Increase it
+				if(method == MULTIPLY)
+				{
+					crntMaxSize *= step;
+				}
+				else
+				{
+					ANKI_ASSERT(method == ADD);
+					crntMaxSize += step;
+				}
 			}
 			}
+			else
+			{
+				// No chunks. Choose initial size
+
+				ANKI_ASSERT(crntChunk == nullptr);
+				crntMaxSize = initSize;
+			}
+
+			ANKI_ASSERT(crntMaxSize > 0);
+
+			// Fix the size
+			crntMaxSize = std::min(crntMaxSize, (PtrSize)maxSize);
 		}
 		}
 
 
-		// Increase it
-		if(chAllocMethod == MULTIPLY)
+		size = crntMaxSize;
+
+		//
+		// Create the chunk
+		//
+		Chunk* chunk = new Chunk(size, alignmentBytes);
+
+		if(chunk)
 		{
 		{
-			crntMaxSize *= chAllocMethodValue;
+			chunks.push_back(chunk);
 		}
 		}
 		else
 		else
 		{
 		{
-			ANKI_ASSERT(chAllocMethod == ADD);
-			crntMaxSize += chAllocMethodValue;
+			throw ANKI_EXCEPTION("Chunk creation failed");
 		}
 		}
+		
+		return chunk;
 	}
 	}
 
 
-	// Fix the size
-	size = std::max(crntMaxSize, size * 2);
-
-	//
-	// Create the chunk
-	//
-	Chunk* chunk = new Chunk(size, alignmentBytes);
-
-	if(chunk)
+	/// Allocate from chunk
+	void* allocateFromChunk(Chunk* ch, PtrSize size) throw()
 	{
 	{
-		chunks.push_back(chunk);
-	}
-	
-	return chunk;
-}
+		ANKI_ASSERT(ch);
+		ANKI_ASSERT(size <= maxSize);
+		void* mem = ch->pool.allocate(size);
 
 
-//==============================================================================
-void* ChainMemoryPool::allocate(PtrSize size) throw()
-{
-	Chunk* ch;
-	void* mem = nullptr;
+		if(mem)
+		{
+			++ch->allocationsCount;
+		}
 
 
-	// Get chunk
-	lock.lock();
-	ch = crntChunk;
-	lock.unlock();
+		return mem;
+	}
 
 
-	// Create new chunk if needed
-	if(ch == nullptr || (mem = allocateFromChunk(ch, size)) == nullptr)
+	/// Allocate memory
+	void* allocate(PtrSize size) throw()
 	{
 	{
-		// Create new chunk
+		Chunk* ch;
+		void* mem = nullptr;
+
 		lock.lock();
 		lock.lock();
 
 
-		crntChunk = createNewChunk(size);
+		// Get chunk
 		ch = crntChunk;
 		ch = crntChunk;
 
 
-		lock.unlock();
+		// Create new chunk if needed
+		if(ch == nullptr || (mem = allocateFromChunk(ch, size)) == nullptr)
+		{
+			// Create new chunk
+			crntChunk = createNewChunk(size);
+			ch = crntChunk;
 
 
-		// Chunk creation failed
-		if(ch == nullptr)
+			// Chunk creation failed
+			if(ch == nullptr)
+			{
+				lock.unlock();
+				return mem;
+			}
+		}
+
+		if(mem == nullptr)
 		{
 		{
-			return mem;
+			mem = allocateFromChunk(ch, size);
+			ANKI_ASSERT(mem != nullptr && "The chunk should have space");
 		}
 		}
+
+		lock.unlock();
+		return mem;
 	}
 	}
 
 
-	if(mem == nullptr)
+	/// Free memory
+	Bool free(void* ptr) throw()
 	{
 	{
-		ANKI_ASSERT(ch != nullptr);
-		mem = allocateFromChunk(ch, size);
-		ANKI_ASSERT(mem != nullptr && "The chunk should have space");
+		lock.lock();
+
+		// Get the chunk that ptr belongs to
+		Vector<Chunk*>::iterator it;
+		for(it = chunks.begin(); it != chunks.end(); it++)
+		{
+			Chunk* ch = *it;
+			ANKI_ASSERT(ch);
+
+			const U8* from = (const U8*)ch->pool.getBaseAddress();
+			const U8* to = from + ch->pool.getTotalSize();
+			const U8* cptr = (const U8*)ptr;
+			if(cptr >= from && cptr < to)
+			{
+				break;
+			}
+		}
+
+		ANKI_ASSERT(it != chunks.end() 
+			&& "Not initialized or ptr is incorrect");
+
+		// Decrease the deallocation refcount and if it's zero delete the chunk
+		ANKI_ASSERT((*it)->allocationsCount > 0);
+		if(--(*it)->allocationsCount == 0)
+		{
+			// Chunk is empty. Delete it
+
+			Chunk* ch = *it;
+			ANKI_ASSERT(ch);
+			
+			delete ch;
+			chunks.erase(it);
+
+			// Change the crntChunk
+			ANKI_ASSERT(crntChunk);
+			if(ch == crntChunk)
+			{
+				// If there are chunks chose the last. It's probably full but
+				// let the allocate() create a new one
+				if(chunks.size() > 0)
+				{
+					crntChunk = chunks.back();
+					ANKI_ASSERT(crntChunk);
+				}
+				else
+				{
+					crntChunk = nullptr;
+				}
+			}
+		}
+
+		lock.unlock();
+
+		return true;
 	}
 	}
+};
+
+//==============================================================================
+ChainMemoryPool::ChainMemoryPool(
+	U32 initialChunkSize,
+	U32 maxChunkSize,
+	ChunkAllocationStepMethod chunkAllocStepMethod, 
+	U32 chunkAllocStep, 
+	U32 alignmentBytes)
+{
+	impl.reset(new Implementation(
+		initialChunkSize, maxChunkSize, chunkAllocStepMethod, chunkAllocStep,
+		alignmentBytes));
+}
 
 
-	return mem;
+//==============================================================================
+ChainMemoryPool::~ChainMemoryPool()
+{}
+
+//==============================================================================
+void* ChainMemoryPool::allocate(PtrSize size) throw()
+{
+	return impl->allocate(size);
+}
+
+//==============================================================================
+Bool ChainMemoryPool::free(void* ptr) throw()
+{
+	return impl->free(ptr);
+}
+
+//==============================================================================
+PtrSize ChainMemoryPool::getChunksCount() const
+{
+	return impl->chunks.size();
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 1 - 1
testapp/Main.cpp

@@ -516,7 +516,7 @@ void mainLoop()
 
 
 		// Sleep
 		// Sleep
 		//
 		//
-#if 1
+#if 0
 		timer.stop();
 		timer.stop();
 		if(timer.getElapsedTime() < AppSingleton::get().getTimerTick())
 		if(timer.getElapsedTime() < AppSingleton::get().getTimerTick())
 		{
 		{

+ 1 - 39
tests/Main.cpp

@@ -3,49 +3,11 @@
 
 
 using namespace anki;
 using namespace anki;
 
 
-struct LoggerMessageHandler
-{
-	ANKI_HAS_SLOTS(LoggerMessageHandler)
-
-	void handleLoggerMessages(const Logger::Info& info)
-	{
-		std::ostream* out = NULL;
-		const char* x = NULL;
-
-		switch(info.type)
-		{
-		case Logger::LMT_NORMAL:
-			out = &std::cout;
-			x = "Info";
-			break;
-
-		case Logger::LMT_ERROR:
-			out = &std::cerr;
-			x = "Error";
-			break;
-
-		case Logger::LMT_WARNING:
-			out = &std::cerr;
-			x = "Warn";
-			break;
-		}
-
-		(*out) << "(" << info.file << ":" << info.line << " "<< info.func 
-			<< ") " << x << ": " << info.msg << std::endl;
-	}
-
-	ANKI_SLOT(handleLoggerMessages, const Logger::Info&)
-};
-
-static LoggerMessageHandler msgh;
-
 int main(int argc, char** argv)
 int main(int argc, char** argv)
 {
 {
 	// Call a few singletons to avoid memory leak confusion
 	// Call a few singletons to avoid memory leak confusion
 	LoggerSingleton::get();
 	LoggerSingleton::get();
-
-	ANKI_CONNECT(&LoggerSingleton::get(), messageRecieved, 
-		&msgh, handleLoggerMessages);
+	LoggerSingleton::get().init(Logger::INIT_SYSTEM_MESSAGE_HANDLER);
 
 
 	int exitcode = getTesterSingleton().run(argc, argv);
 	int exitcode = getTesterSingleton().run(argc, argv);
 
 

+ 0 - 48
tests/core/Async.cpp

@@ -1,48 +0,0 @@
-#include "tests/framework/Framework.h"
-#include "anki/core/Async.h"
-#include "anki/core/Logger.h"
-#include "anki/util/HighRezTimer.h"
-#include "anki/util/StdTypes.h"
-
-namespace anki {
-
-/// Struct for our tests
-struct TestJob: AsyncJob
-{
-	U32 result = 0;
-
-	void operator()()
-	{
-		ANKI_LOGI("-- Job " << this << " starting");
-		HighRezTimer::sleep(1.0);
-		++result;
-		ANKI_LOGI("-- Job " << this << " done");
-	}
-
-	void post()
-	{
-		ANKI_LOGI("-- Job " << this << " starting post");
-		HighRezTimer::sleep(1.0);
-		++result;
-		ANKI_LOGI("-- Job " << this << " done post");
-	}
-};
-
-} // end namespace anki
-
-ANKI_TEST(Core, Async)
-{
-	Async a;
-	TestJob pjob;
-
-	a.start();
-	a.assignNewJob(&pjob);
-
-	HighRezTimer::sleep(2.0);
-
-	a.cleanupFinishedJobs(123.0);
-	a.stop();
-
-	ANKI_TEST_EXPECT_EQ(pjob.result, 2);
-}
-

+ 23 - 4
tests/framework/Framework.cpp

@@ -5,6 +5,15 @@
 
 
 namespace anki {
 namespace anki {
 
 
+//==============================================================================
+TestSuite::~TestSuite()
+{
+	for(Test* t : tests)
+	{
+		delete t;
+	}
+}
+
 //==============================================================================
 //==============================================================================
 void Test::run()
 void Test::run()
 {
 {
@@ -28,7 +37,7 @@ void Test::run()
 void Tester::addTest(const char* name, const char* suiteName,
 void Tester::addTest(const char* name, const char* suiteName,
 	TestCallback callback)
 	TestCallback callback)
 {
 {
-	PtrVector<TestSuite>::iterator it;
+	Vector<TestSuite*>::iterator it;
 	for(it = suites.begin(); it != suites.end(); it++)
 	for(it = suites.begin(); it != suites.end(); it++)
 	{
 	{
 		if((*it)->name == suiteName)
 		if((*it)->name == suiteName)
@@ -51,7 +60,7 @@ void Tester::addTest(const char* name, const char* suiteName,
 	}
 	}
 
 
 	// Sanity check
 	// Sanity check
-	PtrVector<Test>::iterator it1;
+	Vector<Test*>::iterator it1;
 	for(it1 = suite->tests.begin(); it1 != suite->tests.end(); it1++)
 	for(it1 = suite->tests.begin(); it1 != suite->tests.end(); it1++)
 	{
 	{
 		if((*it)->name == name)
 		if((*it)->name == name)
@@ -178,8 +187,18 @@ Options:
 		}
 		}
 	}
 	}
 
 
-	std::cout << "========\nRun " << run << " tests, failed " << (run - passed)
-		<< "\n" << std::endl;
+	int failed = run - passed;
+	std::cout << "========\nRun " << run << " tests, failed " << failed
+		<< std::endl;
+
+	if(failed == 0)
+	{
+		std::cout << "SUCCESS!" << std::endl;
+	}
+	else
+	{
+		std::cout << "FAILURE" << std::endl;
+	}
 
 
 	return run - passed;
 	return run - passed;
 }
 }

+ 12 - 2
tests/framework/Framework.h

@@ -23,7 +23,9 @@ typedef void (*TestCallback)(Test&);
 struct TestSuite
 struct TestSuite
 {
 {
 	std::string name;
 	std::string name;
-	PtrVector<Test> tests;
+	Vector<Test*> tests;
+
+	~TestSuite();
 };
 };
 
 
 /// Test
 /// Test
@@ -39,7 +41,7 @@ struct Test
 /// A container of test suites
 /// A container of test suites
 struct Tester
 struct Tester
 {
 {
-	PtrVector<TestSuite> suites;
+	Vector<TestSuite*> suites;
 	std::string programName;
 	std::string programName;
 
 
 	void addTest(const char* name, const char* suite, TestCallback callback);
 	void addTest(const char* name, const char* suite, TestCallback callback);
@@ -47,6 +49,14 @@ struct Tester
 	int run(int argc, char** argv);
 	int run(int argc, char** argv);
 
 
 	int listTests();
 	int listTests();
+
+	~Tester()
+	{
+		for(TestSuite* s : suites)
+		{
+			delete s;
+		}
+	}
 };
 };
 
 
 /// Singleton so we can do the ANKI_TEST trick
 /// Singleton so we can do the ANKI_TEST trick

+ 6 - 3
tests/util/Allocator.cpp

@@ -3,7 +3,7 @@
 #include "anki/util/Allocator.h"
 #include "anki/util/Allocator.h"
 #include <string>
 #include <string>
 
 
-ANKI_TEST(Allocator, StackAllocator)
+ANKI_TEST(Allocators, StackAllocator)
 {
 {
 	Foo::reset();
 	Foo::reset();
 
 
@@ -21,8 +21,11 @@ ANKI_TEST(Allocator, StackAllocator)
 
 
 	// With vector
 	// With vector
 	{
 	{
-		StackAllocator<Foo> alloc(128);
-		std::vector<Foo, StackAllocator<Foo>> vec(alloc);
+		typedef StackAllocator<Foo, false> All;
+		All alloc(StackMemoryPool((sizeof(Foo) + 1) * 10, 1));
+		std::vector<Foo, All> vec(alloc);
+
+		vec.reserve(10);
 
 
 		U sumi = 0;
 		U sumi = 0;
 		for(U i = 0; i < 10; i++)
 		for(U i = 0; i < 10; i++)

+ 0 - 42
tests/util/DynamicArray.cpp

@@ -1,42 +0,0 @@
-#include "tests/framework/Framework.h"
-#include "tests/util/Foo.h"
-#include "anki/util/DynamicArray.h"
-
-ANKI_TEST(DynamicArray, Test)
-{
-	constexpr U n = 4;
-	StackAllocator<U8, true> alloc(sizeof(Foo) * n + sizeof(PtrSize));
-
-	DynamicArray<Foo, StackAllocator<Foo, true>> arr(alloc);
-
-	arr.resize(n, 1);
-
-	U i = 0;
-	for(const Foo& f : arr)
-	{
-		i += f.x;
-	}
-
-	ANKI_TEST_EXPECT_EQ(i, n);
-
-	arr.clear();
-
-	ANKI_TEST_EXPECT_EQ(arr.getSize(), 0);
-	ANKI_TEST_EXPECT_EQ(alloc.getMemoryPool().getAllocatedSize(), 0);
-
-	// Again
-	arr.resize(n);
-
-	i = 0;
-	for(const Foo& f : arr)
-	{
-		i += f.x;
-	}
-
-	ANKI_TEST_EXPECT_EQ(i, n * 666);
-
-	arr.clear();
-
-	ANKI_TEST_EXPECT_EQ(arr.getSize(), 0);
-	ANKI_TEST_EXPECT_EQ(alloc.getMemoryPool().getAllocatedSize(), 0);
-}

+ 43 - 3
tests/util/Memory.cpp

@@ -3,9 +3,9 @@
 #include "anki/util/Memory.h"
 #include "anki/util/Memory.h"
 #include <type_traits>
 #include <type_traits>
 
 
-ANKI_TEST(Memory, Test)
+ANKI_TEST(Memory, StackMemoryPool)
 {
 {
-	constexpr U n = 4;
+	/*constexpr U n = 4;
 	StackAllocator<U8, true> alloc(sizeof(Foo) * n + sizeof(PtrSize));
 	StackAllocator<U8, true> alloc(sizeof(Foo) * n + sizeof(PtrSize));
 
 
 	Foo* f = ANKI_NEW(Foo, alloc, 123);
 	Foo* f = ANKI_NEW(Foo, alloc, 123);
@@ -29,6 +29,46 @@ ANKI_TEST(Memory, Test)
 
 
 	ANKI_DELETE_ARRAY(f, alloc);
 	ANKI_DELETE_ARRAY(f, alloc);
 
 
-	ANKI_TEST_EXPECT_EQ(alloc.getMemoryPool().getAllocatedSize(), 0);
+	ANKI_TEST_EXPECT_EQ(alloc.getMemoryPool().getAllocatedSize(), 0);*/
 }
 }
 
 
+ANKI_TEST(Memory, ChainMemoryPool)
+{
+	// Basic test
+	{
+		const U size = sizeof(PtrSize) + 10;
+		ChainMemoryPool pool(
+			size, size, ChainMemoryPool::MULTIPLY, 2, 1);
+
+		void* mem = pool.allocate(1);
+		ANKI_TEST_EXPECT_NEQ(mem, nullptr);
+		ANKI_TEST_EXPECT_EQ(pool.getChunksCount(), 1);
+
+		void* mem1 = pool.allocate(10);
+		ANKI_TEST_EXPECT_NEQ(mem1, nullptr);
+		ANKI_TEST_EXPECT_EQ(pool.getChunksCount(), 2);
+
+		pool.free(mem1);
+		pool.free(mem);
+		ANKI_TEST_EXPECT_EQ(pool.getChunksCount(), 0);
+	}
+
+	// Basic test 2
+	{
+		const U size = sizeof(PtrSize) + 10;
+		ChainMemoryPool pool(
+			size, size, ChainMemoryPool::MULTIPLY, 2, 1);
+
+		void* mem = pool.allocate(1);
+		ANKI_TEST_EXPECT_NEQ(mem, nullptr);
+		ANKI_TEST_EXPECT_EQ(pool.getChunksCount(), 1);
+
+		void* mem1 = pool.allocate(10);
+		ANKI_TEST_EXPECT_NEQ(mem1, nullptr);
+		ANKI_TEST_EXPECT_EQ(pool.getChunksCount(), 2);
+
+		pool.free(mem);
+		pool.free(mem1);
+		ANKI_TEST_EXPECT_EQ(pool.getChunksCount(), 0);
+	}
+}

+ 3 - 0
tests/util/Object.cpp

@@ -3,6 +3,8 @@
 
 
 using namespace anki;
 using namespace anki;
 
 
+#if 0
+
 template<typename T, typename Alloc>
 template<typename T, typename Alloc>
 struct Deleter
 struct Deleter
 {
 {
@@ -79,4 +81,5 @@ ANKI_TEST(Object, Test)
 	delete a;
 	delete a;
 }
 }
 
 
+#endif
 
 

+ 9 - 8
tests/core/ThreadPool.cpp → tests/util/Thread.cpp

@@ -1,17 +1,16 @@
 #include "tests/framework/Framework.h"
 #include "tests/framework/Framework.h"
-#include "anki/core/ThreadPool.h"
-#include "anki/core/Logger.h"
+#include "anki/util/Thread.h"
 #include "anki/util/StdTypes.h"
 #include "anki/util/StdTypes.h"
 
 
 namespace anki {
 namespace anki {
 
 
 /// Struct for our tests
 /// Struct for our tests
-struct TestJobTP: ThreadJob
+struct TestJobTP: ThreadpoolTask
 {
 {
 	U32 in = 0;
 	U32 in = 0;
 	U32 iterations = 0;
 	U32 iterations = 0;
 
 
-	void operator()(U /*threadId*/, U /*threadsCount*/)
+	void operator()(ThreadId /*threadId*/, U /*threadsCount*/)
 	{
 	{
 		for(U32 i = 0; i < iterations; i++)	
 		for(U32 i = 0; i < iterations; i++)	
 		{
 		{
@@ -22,11 +21,11 @@ struct TestJobTP: ThreadJob
 
 
 } // end namespace anki
 } // end namespace anki
 
 
-ANKI_TEST(Core, ThreadPool)
+ANKI_TEST(Core, Threadpool)
 {
 {
 	const U32 threadsCount = 4;
 	const U32 threadsCount = 4;
 	const U32 repeat = 500;
 	const U32 repeat = 500;
-	ThreadPool* tp = new ThreadPool;
+	Threadpool* tp = new Threadpool;
 
 
 	tp->init(threadsCount);
 	tp->init(threadsCount);
 	TestJobTP jobs[threadsCount];
 	TestJobTP jobs[threadsCount];
@@ -40,15 +39,17 @@ ANKI_TEST(Core, ThreadPool)
 			jobs[j].in = i;
 			jobs[j].in = i;
 			jobs[j].iterations = iterations;
 			jobs[j].iterations = iterations;
 
 
-			tp->assignNewJob(j, &jobs[j]);
+			tp->assignNewTask(j, &jobs[j]);
 		}
 		}
 
 
-		tp->waitForAllJobsToFinish();
+		tp->waitForAllThreadsToFinish();
 
 
 		for(U32 j = 0; j < threadsCount; j++)
 		for(U32 j = 0; j < threadsCount; j++)
 		{
 		{
 			ANKI_TEST_EXPECT_EQ(jobs[j].in, i + iterations);
 			ANKI_TEST_EXPECT_EQ(jobs[j].in, i + iterations);
 		}
 		}
 	}
 	}
+
+	delete tp;
 }
 }