Browse Source

Allocator stuff

Panagiotis Christopoulos Charitos 13 years ago
parent
commit
12f0e81cca

+ 2 - 2
include/anki/core/ThreadPool.h

@@ -118,8 +118,8 @@ public:
 	}
 	}
 
 
 private:
 private:
-	DynamicArray<ThreadWorker*> jobs; ///< Worker threads
-	Barrier* barrier = nullptr; ///< Synchronization barrier
+	Vector<ThreadWorker*> jobs; ///< Worker threads
+	std::unique_ptr<Barrier> barrier; ///< Synchronization barrier
 };
 };
 
 
 /// Singleton
 /// Singleton

+ 4 - 2
include/anki/scene/Scene.h

@@ -43,9 +43,11 @@ public:
 
 
 	/// @name Accessors
 	/// @name Accessors
 	/// @{
 	/// @{
-	const SceneAllocator<U8>& getAllocator() const
+
+	/// Return a copy
+	SceneAllocator<U8> getAllocator() const
 	{
 	{
-		return alloc;
+		return SceneAllocator<U8>(alloc);
 	}
 	}
 
 
 	const Vec3& getAmbientColor() const
 	const Vec3& getAmbientColor() const

+ 3 - 1
include/anki/scene/SceneNode.h

@@ -49,6 +49,8 @@ public:
 	{
 	{
 		return *scene;
 		return *scene;
 	}
 	}
+
+	SceneAllocator<U8> getSceneAllocator() const;
 	/// @}
 	/// @}
 
 
 	/// @name Accessors of components
 	/// @name Accessors of components
@@ -101,7 +103,7 @@ public:
 
 
 private:
 private:
 	SceneString name; ///< A unique name
 	SceneString name; ///< A unique name
-	Scene* scene; ///< Keep it here for unregistering
+	Scene* scene = nullptr; ///< Keep it here for unregistering
 };
 };
 /// @}
 /// @}
 
 

+ 27 - 12
include/anki/util/DynamicArray.h

@@ -2,7 +2,6 @@
 #define ANKI_UTIL_DYNAMIC_ARRAY_H
 #define ANKI_UTIL_DYNAMIC_ARRAY_H
 
 
 #include "anki/util/Allocator.h"
 #include "anki/util/Allocator.h"
-#include "anki/util/Memory.h"
 
 
 namespace anki {
 namespace anki {
 
 
@@ -84,6 +83,7 @@ public:
 		allocator = b.allocator;
 		allocator = b.allocator;
 
 
 		other.b = nullptr;
 		other.b = nullptr;
+		other.e = nullptr;
 
 
 		return *this;
 		return *this;
 	}
 	}
@@ -122,21 +122,22 @@ public:
 		return e - b;
 		return e - b;
 	}
 	}
 
 
-	/// Resize the array
-	void resize(const PtrSize n)
-	{
-		ANKI_ASSERT(b == nullptr);
-		b = New<Value, Alloc>(n, allocator)();
-		e = b + n;
-	}
-
 	/// Resize the array and call the constructors
 	/// Resize the array and call the constructors
 	template<typename... Args>
 	template<typename... Args>
 	void resize(const PtrSize n, Args&&... args)
 	void resize(const PtrSize n, Args&&... args)
 	{
 	{
-		ANKI_ASSERT(b == nullptr);
-		b = New<Value, Alloc>(n, allocator)(std::forward<Args>(args)...);
+		ANKI_ASSERT(b == nullptr && e == nullptr);
+		ANKI_ASSERT(n > 0);
+
+		// Allocate memory
+		b = allocator.allocate(n);
 		e = b + n;
 		e = b + n;
+
+		// Call the constructors
+		for(PtrSize i = 0; i < n; i++)
+		{
+			allocator.construct(b + i, std::forward<Args>(args)...);
+		}
 	}
 	}
 
 
 	/// Clear the array
 	/// Clear the array
@@ -144,7 +145,21 @@ public:
 	{
 	{
 		if(b)
 		if(b)
 		{
 		{
-			DeleteArray<Value, Alloc>{allocator}(b);
+			ANKI_ASSERT(e != nullptr);
+
+			PtrSize n = getSize();
+			ANKI_ASSERT(n > 0);
+
+			// Call the destructors
+			for(PtrSize i = 0; i < n; i++)
+			{
+				allocator.destroy(b + i);
+			}
+
+			// Deallocate the memory
+			allocator.deallocate(b, n);
+
+			// Reset the data
 			b = nullptr;
 			b = nullptr;
 			e = nullptr;
 			e = nullptr;
 		}
 		}

+ 4 - 0
include/anki/util/Memory.h

@@ -10,6 +10,8 @@ namespace anki {
 /// @addtogroup memory
 /// @addtogroup memory
 /// @{
 /// @{
 
 
+#if 0
+
 /// Function that imitates the new operator. The function allocates memory for
 /// Function that imitates the new operator. The function allocates memory for
 /// a number of elements and calls their constructor. The interesting thing is
 /// a number of elements and calls their constructor. The interesting thing is
 /// that if the elements size is >1 then it allocates size bigger than the
 /// that if the elements size is >1 then it allocates size bigger than the
@@ -132,6 +134,8 @@ struct DeleteArray
 	}
 	}
 };
 };
 
 
+#endif
+
 /// @}
 /// @}
 /// @}
 /// @}
 
 

+ 55 - 17
include/anki/util/Observer.h

@@ -24,30 +24,60 @@ struct Observer
 };
 };
 
 
 /// An over-qualified observer
 /// An over-qualified observer
-template<typename ObservingType, typename Value,
-	void (ObservingType::*method)(Value)>
+template<typename ObservingClass, typename Value,
+	void (ObservingClass::*method)(Value)>
 struct SuperObserver: Observer<Value>
 struct SuperObserver: Observer<Value>
 {
 {
-	ObservingType* reveiver;
+	ObservingClass* receiver;
 
 
-	SuperObserver(ObservingType* reveiver_)
-		: reveiver(reveiver_)
-	{}
+	SuperObserver(ObservingClass* receiver_)
+		: receiver(receiver_)
+	{
+		ANKI_ASSERT(receiver != nullptr);
+	}
 
 
 	void notify(Value x)
 	void notify(Value x)
 	{
 	{
-		(reveiver->*method)(x);
+		(receiver->*method)(x);
 	}
 	}
 };
 };
 
 
 /// Basically a container of observers
 /// Basically a container of observers
-template<typename T>
+template<typename T, typename Alloc = Allocator<Observer<T>*>>
 class Observable
 class Observable
 {
 {
 public:
 public:
 	typedef T Value;
 	typedef T Value;
 	typedef Observer<Value> ObserverType;
 	typedef Observer<Value> ObserverType;
-	typedef PtrVector<ObserverType> Container;
+	typedef Vector<ObserverType*, Alloc> Container;
+
+	Observable(const Alloc& alloc = Alloc())
+		: observers(alloc)
+	{}
+
+	~Observable()
+	{
+		Alloc alloc = observers.get_allocator();
+		for(ObserverType* x : observers)
+		{
+			alloc.destroy(x);
+			alloc.deallocate(x, 1);
+		}
+	}
+
+	/// XXX
+	template<typename Observer, typename... Args>
+	Observer* newObserver(Args&&... args)
+	{
+		typedef typename Alloc::template rebind<Observer>::other UberAlloc;
+
+		UberAlloc alloc(observers.get_allocator());
+
+		Observer* ptr = alloc.allocate(1);
+		alloc.construct(ptr, std::forward<Args>(args)...);
+
+		return ptr;
+	}
 
 
 	/// Add a new observer. The Observable takes ownership of the
 	/// Add a new observer. The Observable takes ownership of the
 	/// pointer and its responsible of cleaning
 	/// pointer and its responsible of cleaning
@@ -59,10 +89,9 @@ public:
 	/// Notify all observers
 	/// Notify all observers
 	void notifyAll(Value x)
 	void notifyAll(Value x)
 	{
 	{
-		for(typename Container::iterator it = observers.begin();
-			it != observers.end(); ++it)
+		for(ObserverType* obs : observers)
 		{
 		{
-			(*it)->notify(x);
+			obs->notify(x);
 		}
 		}
 	}
 	}
 
 
@@ -95,14 +124,18 @@ private:
 /// 	ANKI_SLOT(updateZFar, const float&)
 /// 	ANKI_SLOT(updateZFar, const float&)
 /// };
 /// };
 /// @endcode
 /// @endcode
-#define ANKI_SLOT(_name, _type) \
-	typedef SuperObserver<ObservingType, _type, &ObservingType::_name> \
-		Observing_##_name;
+#define ANKI_SLOT(_slot, _type) \
+	typedef SuperObserver<ObservingType, _type, &ObservingType::_slot> \
+		Observing_##_slot;
 
 
 /// Define a signal
 /// Define a signal
 #define ANKI_SIGNAL(_type, _name) \
 #define ANKI_SIGNAL(_type, _name) \
 	Observable<_type> _name;
 	Observable<_type> _name;
 
 
+/// Define a signal with allocator
+#define ANKI_SIGNAL_ALLOCATOR(_Type, _name, _AllocType) \
+	Observable<_Type, _AllocType> _name;
+
 /// It doesn't do anything. Its purpose is to make the code more understandable
 /// It doesn't do anything. Its purpose is to make the code more understandable
 #define ANKI_EMIT this->
 #define ANKI_EMIT this->
 
 
@@ -110,8 +143,13 @@ private:
 /// @note Use RemovePointer so you can be able to use the macro outside of the
 /// @note Use RemovePointer so you can be able to use the macro outside of the
 ///       _receiver body
 ///       _receiver body
 #define ANKI_CONNECT(_sender, _signal, _receiver, _slot) \
 #define ANKI_CONNECT(_sender, _signal, _receiver, _slot) \
-	(_sender)->_signal.addNewObserver( new \
-		RemovePointer<decltype(_receiver)>::Type::Observing_##_slot(_receiver))
+	do { \
+		auto observer = (_sender)->_signal.newObserver< \
+			RemovePointer<decltype(_receiver)>::Type::Observing_##_slot>( \
+			_receiver); \
+		(_sender)->_signal.addNewObserver(observer); \
+	} while(false);
+
 /// @}
 /// @}
 /// @}
 /// @}
 
 

+ 3 - 5
src/core/ThreadPool.cpp

@@ -60,10 +60,8 @@ ThreadPool::~ThreadPool()
 {
 {
 	for(ThreadWorker* thread : jobs)
 	for(ThreadWorker* thread : jobs)
 	{
 	{
-		Delete<ThreadWorker>{}(thread);
+		delete thread;
 	}
 	}
-
-	Delete<Barrier>{}(barrier);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -71,13 +69,13 @@ void ThreadPool::init(U threadsNum)
 {
 {
 	ANKI_ASSERT(threadsNum <= MAX_THREADS);
 	ANKI_ASSERT(threadsNum <= MAX_THREADS);
 
 
-	barrier = New<Barrier>{}(threadsNum + 1);
+	barrier.reset(new Barrier(threadsNum + 1));
 
 
 	jobs.resize(threadsNum);
 	jobs.resize(threadsNum);
 
 
 	for(U i = 0; i < threadsNum; i++)
 	for(U i = 0; i < threadsNum; i++)
 	{
 	{
-		jobs[i] = New<ThreadWorker>{}(i, barrier, this);
+		jobs[i] = new ThreadWorker(i, barrier.get(), this);
 	}
 	}
 }
 }
 
 

+ 7 - 0
src/scene/SceneNode.cpp

@@ -23,6 +23,13 @@ SceneNode::~SceneNode()
 	scene->unregisterNode(this);
 	scene->unregisterNode(this);
 }
 }
 
 
+//==============================================================================
+SceneAllocator<U8> SceneNode::getSceneAllocator() const
+{
+	ANKI_ASSERT(scene);
+	return scene->getAllocator();
+}
+
 //==============================================================================
 //==============================================================================
 U32 SceneNode::getLastUpdateFrame()
 U32 SceneNode::getLastUpdateFrame()
 {
 {

+ 1 - 1
src/util/CMakeLists.txt

@@ -1,4 +1,4 @@
-SET(ANKI_UTIL_SOURCES Assert.cpp BinaryStream.cpp Exception.cpp Functions.cpp Scanner.cpp StringList.cpp Filesystem.cpp Allocator.cpp)
+SET(ANKI_UTIL_SOURCES Assert.cpp BinaryStream.cpp Exception.cpp Functions.cpp Scanner.cpp StringList.cpp Filesystem.cpp Allocator.cpp Memory.cpp)
 
 
 IF(ANKI_PLATFORM STREQUAL "LINUX")
 IF(ANKI_PLATFORM STREQUAL "LINUX")
 	SET(ANKI_UTIL_SOURCES ${ANKI_UTIL_SOURCES} HighRezTimerPosix.cpp FilesystemPosix.cpp)
 	SET(ANKI_UTIL_SOURCES ${ANKI_UTIL_SOURCES} HighRezTimerPosix.cpp FilesystemPosix.cpp)

+ 16 - 0
tests/util/DynamicArray.cpp

@@ -23,4 +23,20 @@ ANKI_TEST(DynamicArray, Test)
 
 
 	ANKI_TEST_EXPECT_EQ(arr.getSize(), 0);
 	ANKI_TEST_EXPECT_EQ(arr.getSize(), 0);
 	ANKI_TEST_EXPECT_EQ(alloc.dump(), true);
 	ANKI_TEST_EXPECT_EQ(alloc.dump(), true);
+
+	// 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.dump(), true);
 }
 }

+ 2 - 2
tests/util/Memory.cpp

@@ -4,7 +4,7 @@
 
 
 ANKI_TEST(Memory, Test)
 ANKI_TEST(Memory, Test)
 {
 {
-	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 = New<Foo, StackAllocator<Foo, true>>(n, alloc)();
 	Foo* f = New<Foo, StackAllocator<Foo, true>>(n, alloc)();
@@ -13,6 +13,6 @@ ANKI_TEST(Memory, Test)
 
 
 	DeleteArray<Foo, StackAllocator<Foo, true>>{alloc}(f);
 	DeleteArray<Foo, StackAllocator<Foo, true>>{alloc}(f);
 
 
-	ANKI_TEST_EXPECT_EQ(alloc.dump(), true);
+	ANKI_TEST_EXPECT_EQ(alloc.dump(), true);*/
 }
 }