Browse Source

Dynamic array + unit tests

Panagiotis Christopoulos Charitos 13 years ago
parent
commit
ea1b9a9983

+ 5 - 5
include/anki/scene/Camera.h

@@ -51,9 +51,9 @@ public:
 	}
 
 	/// Needed by the renderer
-	virtual float getNear() const = 0;
+	virtual F32 getNear() const = 0;
 	/// Needed by the renderer
-	virtual float getFar() const = 0;
+	virtual F32 getFar() const = 0;
 	/// @}
 
 	/// @name SceneNode virtuals
@@ -78,7 +78,7 @@ public:
 	}
 
 	/// Override SceneNode::frameUpdate
-	void frameUpdate(float prevUpdateTime, float crntTime, int frame)
+	void frameUpdate(F32 prevUpdateTime, F32 crntTime, int frame)
 	{
 		SceneNode::frameUpdate(prevUpdateTime, crntTime, frame);
 	}
@@ -125,12 +125,12 @@ public:
 
 	/// @name Accessors
 	/// @{
-	float getNear() const
+	F32 getNear() const
 	{
 		return frustum.getNear();
 	}
 
-	float getFar() const
+	F32 getFar() const
 	{
 		return frustum.getFar();
 	}

+ 10 - 0
include/anki/scene/Scene.h

@@ -32,6 +32,9 @@ public:
 		typedef typename ConstCharPtrHashMap<T*>::Type NameToItemMap;
 	};
 
+	/// The size of the internal allocator
+	const PtrSize ALLOCATOR_SIZE = 0x100000;
+
 	/// @name Constructors/Destructor
 	/// @{
 	Scene();
@@ -40,6 +43,11 @@ public:
 
 	/// @name Accessors
 	/// @{
+	const SceneAllocator<U8> getAllocator() const
+	{
+		return alloc;
+	}
+
 	const Vec3& getAmbientColor() const
 	{
 		return ambientCol;
@@ -112,6 +120,8 @@ public:
 	PtrVector<Sector> sectors;
 
 private:
+	SceneAllocator<U8> alloc;
+
 	Vec3 ambientCol = Vec3(1.0); ///< The global ambient color
 	U32 ambiendColorUpdateTimestamp = Timestamp::getTimestamp();
 	Camera* mainCam = nullptr;

+ 10 - 0
include/anki/scene/SceneNode.h

@@ -2,6 +2,7 @@
 #define ANKI_SCENE_SCENE_NODE_H
 
 #include "anki/scene/Property.h"
+#include "anki/util/Allocator.h"
 #include <string>
 
 namespace anki {
@@ -19,6 +20,10 @@ class RigidBody;
 /// @addtogroup Scene
 /// @{
 
+/// XXX
+template<typename T>
+using SceneAllocator = StackAllocator<T, false>;
+
 /// Interface class backbone of scene
 class SceneNode: public PropertyMap
 {
@@ -43,6 +48,11 @@ public:
 	{
 		return name;
 	}
+
+	Scene& getScene()
+	{
+		return *scene;
+	}
 	/// @}
 
 	/// @name Accessors of components

+ 1 - 0
include/anki/util/Allocator.h

@@ -6,6 +6,7 @@
 #include <cstddef> // For ptrdiff_t
 #include <cstring> // For memset
 #include <atomic>
+#include <utility> // For forward
 
 #define ANKI_DEBUG_ALLOCATORS ANKI_DEBUG
 #define ANKI_PRINT_ALLOCATOR_MESSAGES 0

+ 18 - 4
include/anki/util/ConstCharPtrHashMap.h

@@ -1,11 +1,17 @@
 #ifndef ANKI_UTIL_CONST_CHAR_PTR_HASH_MAP_H
 #define ANKI_UTIL_CONST_CHAR_PTR_HASH_MAP_H
 
+#include "anki/util/Allocator.h"
 #include <unordered_map>
 #include <cstring>
 
 namespace anki {
 
+/// @addtogroup util
+/// @{
+/// @addtogroup containers
+/// @{
+
 /// The hash function
 struct CreateCharPtrHashMapKey
 {
@@ -32,13 +38,21 @@ struct CompareCharPtrHashMapKeys
 /// The hash map that has as key an old school C string. When inserting the
 /// char MUST NOT point to a temporary or the evaluation function will fail.
 /// Its template struct because C++ does not offer template typedefs
-template<typename T>
+template<
+	typename T,
+	typename Alloc = Allocator<std::pair<const char*, T>>>
 struct ConstCharPtrHashMap
 {
-	typedef std::unordered_map<const char*, T,
-		CreateCharPtrHashMapKey, CompareCharPtrHashMapKeys> Type;
+	typedef std::unordered_map<
+		const char*,
+		T,
+		CreateCharPtrHashMapKey,
+		CompareCharPtrHashMapKeys,
+		Alloc> Type;
 };
+/// @}
+/// @}
 
-} // end namespace
+} // end namespace anki
 
 #endif

+ 79 - 3
include/anki/util/DynamicArray.h

@@ -2,6 +2,7 @@
 #define ANKI_UTIL_DYNAMIC_ARRAY_H
 
 #include "anki/util/Allocator.h"
+#include "anki/util/Memory.h"
 
 namespace anki {
 
@@ -23,57 +24,132 @@ public:
 	/// @name Constructors/destructor
 	/// @{
 
-	/// XXX
+	/// Default
 	DynamicArray()
 	{}
-	/// XXX
-	DynamicArray(const PtrSize n)
+
+	/// Copy is deleted
+	DynamicArray(const DynamicArray&) = delete;
+
+	/// Move
+	DynamicArray(DynamicArray&& other)
+		: b(other.e), e(other.e), allocator(other.allocator)
 	{
+		other.b = nullptr;
+	}
 
+	/// Allocate the array
+	DynamicArray(const PtrSize n, const Alloc& alloc = Alloc())
+		: allocator(alloc)
+	{
+		resize(n);
+	}
+
+	///
+	DynamicArray(const Alloc& alloc)
+		: allocator(alloc)
+	{}
+
+	/// Deallocate
+	~DynamicArray()
+	{
+		clear();
 	}
 	/// @}
 
 	Reference operator[](const PtrSize n)
 	{
+		ANKI_ASSERT(b != nullptr);
 		ANKI_ASSERT(n < getSize());
 		return *(begin + n);
 	}
 
 	ConstReference operator[](const PtrSize n) const
 	{
+		ANKI_ASSERT(b != nullptr);
 		ANKI_ASSERT(n < getSize());
 		return *(begin + n);
 	}
 
+	/// Copy is not permited
+	DynamicArray& operator=(const Foo&) = delete;
+
+	/// Move
+	DynamicArray& operator=(DynamicArray&& other)
+	{
+		clear();
+
+		b = other.b;
+		e = other.e;
+		allocator = b.allocator;
+
+		other.b = nullptr;
+
+		return *this;
+	}
+
 	/// Make it compatible with the C++11 range based for loop
 	Iterator begin()
 	{
+		ANKI_ASSERT(b != nullptr);
 		return b;
 	}
 
 	/// Make it compatible with the C++11 range based for loop
 	ConstIterator begin() const
 	{
+		ANKI_ASSERT(b != nullptr);
 		return b;
 	}
 
 	/// Make it compatible with the C++11 range based for loop
 	Iterator end()
 	{
+		ANKI_ASSERT(b != nullptr);
 		return e;
 	}
 
 	/// Make it compatible with the C++11 range based for loop
 	ConstIterator end() const
 	{
+		ANKI_ASSERT(b != nullptr);
 		return e;
 	}
 
+	/// Get the elements count
 	PtrSize getSize() const
 	{
 		return e - b;
 	}
 
+	/// Resize the array
+	void resize(const PtrSize n)
+	{
+		ANKI_ASSERT(b == nullptr);
+		b = newObject<Value>(allocator, n);
+		e = b + n;
+	}
+
+	/// Resize the array and call the constructors
+	template<typename... Args>
+	void resize(const PtrSize n, Args&&... args)
+	{
+		ANKI_ASSERT(b == nullptr);
+		b = newObject<Value>(allocator, n, std::forward<Args>(args)...);
+		e = b + n;
+	}
+
+	/// Clear the array
+	void clear()
+	{
+		if(b)
+		{
+			deleteObjectArray<Value>(allocator, b);
+			b = nullptr;
+			e = nullptr;
+		}
+	}
+
 private:
 	Value* b = nullptr;
 	Value* e = nullptr;

+ 3 - 1
src/scene/ParticleEmitter.cpp

@@ -87,7 +87,9 @@ void ParticleSimple::simulate(const ParticleEmitter& pe,
 {
 	F32 dt = crntTime - prevUpdateTime;
 
-	ANKI_ASSERT(props.particle.gravity.getLength() > 0.0);
+	ANKI_ASSERT(
+		static_cast<const ParticleEmitterProperties&>(pe).
+		particle.gravity.getLength() > 0.0);
 
 	Transform trf = getWorldTransform();
 	Vec3 xp = trf.getOrigin();

+ 1 - 0
src/scene/Scene.cpp

@@ -39,6 +39,7 @@ struct UpdateMovablesJob: ThreadJob
 
 //==============================================================================
 Scene::Scene()
+	: alloc(ALLOCATOR_SIZE)
 {
 	ambientCol = Vec3(0.1, 0.05, 0.05) * 2;
 }

+ 25 - 0
tests/util/DynamicArray.cpp

@@ -0,0 +1,25 @@
+#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);
+}

+ 40 - 0
tests/util/Foo.h

@@ -0,0 +1,40 @@
+#ifndef ANKI_TESTS_UTIL_FOO_H
+#define ANKI_TESTS_UTIL_FOO_H
+
+/// Struct for testing
+struct Foo
+{
+	int x = 666;
+
+	Foo()
+	{}
+
+	Foo(int x_)
+		: x(x_)
+	{}
+
+	Foo(const Foo& b)
+		: x(b.x)
+	{}
+
+	Foo(Foo&& b)
+		: x(b.x)
+	{
+		b.x = 0;
+	}
+
+	Foo& operator=(const Foo& b)
+	{
+		x = b.x;
+		return *this;
+	}
+
+	Foo& operator=(Foo&& b)
+	{
+		x = b.x;
+		b.x = 0;
+		return *this;
+	}
+};
+
+#endif