Ver código fonte

Use Bitsquid TempAllocator

Daniele Bartolini 10 anos atrás
pai
commit
e589fdd329
1 arquivos alterados com 85 adições e 99 exclusões
  1. 85 99
      src/core/memory/temp_allocator.h

+ 85 - 99
src/core/memory/temp_allocator.h

@@ -15,110 +15,96 @@
 
 namespace crown
 {
-
-/// Allocates from a fixed-size buffer.
-/// When the internal memory is exhausted or the allocation size exceeds
-/// the remainig internal storage, the backing allocator is used instead.
-/// The memory is automatically freed when the allocator is destroyed.
-///
-/// @ingroup Memory
-template <uint32_t SIZE>
-class TempAllocator : public Allocator
-{
-public:
-
-	/// Uses the @a backing allocator when internal memory is exahusted
-	/// or the allocation size exceeds the remaining storage.
-	TempAllocator(Allocator& backing = default_scratch_allocator());
-	~TempAllocator();
-
-	/// @copydoc Allocator::allocate()
-	void* allocate(uint32_t size, uint32_t align = Allocator::DEFAULT_ALIGN);
-
-	/// Does nothing, the memory is automatically freed when the
-	/// allocator is destroyed.
-	void deallocate(void* /*data*/) {}
-
-	/// @copydoc Allocator::allocated_size()
-	uint32_t allocated_size(const void* /*ptr*/) { return SIZE_NOT_TRACKED; }
-
-	/// @copydoc Allocator::total_allocated()
-	uint32_t total_allocated() { return SIZE_NOT_TRACKED; }
-
-private:
-
-	Allocator&	_backing;
-
-	char* _begin;
-	char* _end;
-	char* _cur;
-	uint32_t _chunk_size;
-	char _buffer[SIZE];
-};
-
-typedef TempAllocator<64> TempAllocator64;
-typedef TempAllocator<128> TempAllocator128;
-typedef TempAllocator<256> TempAllocator256;
-typedef TempAllocator<512> TempAllocator512;
-typedef TempAllocator<1024> TempAllocator1024;
-typedef TempAllocator<2048> TempAllocator2048;
-typedef TempAllocator<4096> TempAllocator4096;
-
-template <uint32_t SIZE>
-inline TempAllocator<SIZE>::TempAllocator(Allocator& backing)
-	: _backing(backing)
-	, _begin(&_buffer[0])
-	, _end(&_buffer[SIZE - 1])
-	, _cur(&_buffer[0])
-	, _chunk_size(4 * 1024)
-{
-	*(void**) _begin = 0;
-	_cur += sizeof(void*);
-}
-
-template <uint32_t SIZE>
-inline TempAllocator<SIZE>::~TempAllocator()
-{
-	union { char* as_char; void** as_dvoid; };
-	as_char = _buffer;
-
-	void *p = *(void **)as_dvoid;
-	while (p)
+	/// A temporary memory allocator that primarily allocates memory from a
+	/// local stack buffer of size BUFFER_SIZE. If that memory is exhausted it will
+	/// use the backing allocator (typically a scratch allocator).
+	///
+	/// Memory allocated with a TempAllocator does not have to be deallocated. It is
+	/// automatically deallocated when the TempAllocator is destroyed.
+	template <int BUFFER_SIZE>
+	class TempAllocator : public Allocator
 	{
-		void *next = *(void **)p;
-		_backing.deallocate(p);
-		p = next;
+	public:
+
+		/// Creates a new temporary allocator using the specified backing allocator.
+		TempAllocator(Allocator &backing = default_scratch_allocator());
+		virtual ~TempAllocator();
+
+		virtual void *allocate(uint32_t size, uint32_t align = DEFAULT_ALIGN);
+
+		/// Deallocation is a NOP for the TempAllocator. The memory is automatically
+		/// deallocated when the TempAllocator is destroyed.
+		virtual void deallocate(void *) {}
+
+		/// Returns SIZE_NOT_TRACKED.
+		virtual uint32_t allocated_size(const void*) {return SIZE_NOT_TRACKED;}
+
+		/// Returns SIZE_NOT_TRACKED.
+		virtual uint32_t total_allocated() {return SIZE_NOT_TRACKED;}
+
+	private:
+
+		char _buffer[BUFFER_SIZE];	//< Local stack buffer for allocations.
+		Allocator &_backing;		//< Backing allocator if local memory is exhausted.
+		char *_start;				//< Start of current allocation region
+		char *_p;					//< Current allocation pointer.
+		char *_end;					//< End of current allocation region
+		unsigned _chunk_size;		//< Chunks to allocate from backing allocator
+	};
+
+	// If possible, use one of these predefined sizes for the TempAllocator to avoid
+	// unnecessary template instantiation.
+	typedef TempAllocator<64> TempAllocator64;
+	typedef TempAllocator<128> TempAllocator128;
+	typedef TempAllocator<256> TempAllocator256;
+	typedef TempAllocator<512> TempAllocator512;
+	typedef TempAllocator<1024> TempAllocator1024;
+	typedef TempAllocator<2048> TempAllocator2048;
+	typedef TempAllocator<4096> TempAllocator4096;
+
+	// ---------------------------------------------------------------
+	// Inline function implementations
+	// ---------------------------------------------------------------
+
+	template <int BUFFER_SIZE>
+	TempAllocator<BUFFER_SIZE>::TempAllocator(Allocator &backing) : _backing(backing), _chunk_size(4*1024)
+	{
+		_p = _start = _buffer;
+		_end = _start + BUFFER_SIZE;
+		*(void **)_start = 0;
+		_p += sizeof(void *);
 	}
-}
-
-template <uint32_t SIZE>
-inline void* TempAllocator<SIZE>::allocate(uint32_t size, uint32_t align)
-{
-	_cur = (char*) memory::align_top(_cur, align);
 
-	if (size > uint32_t(_end - _cur))
+	template <int BUFFER_SIZE>
+	TempAllocator<BUFFER_SIZE>::~TempAllocator()
 	{
-		uint32_t to_allocate = sizeof(void*) + size + align;
-
-		if (to_allocate < _chunk_size)
-		{
-			to_allocate = _chunk_size;
+		void *p = *(void **)_buffer;
+		while (p) {
+			void *next = *(void **)p;
+			_backing.deallocate(p);
+			p = next;
 		}
-
-		_chunk_size *= 2;
-
-		void *p = _backing.allocate(to_allocate);
-		*(void **)_begin = p;
-		_cur = _begin = (char*) p;
-		_end = _begin + to_allocate;
-		*(void**) _begin = 0;
-		_cur += sizeof(void*);
-		memory::align_top(p, align);
 	}
 
-	void *result = _cur;
-	_cur += size;
-	return result;
-}
-
+	template <int BUFFER_SIZE>
+	void *TempAllocator<BUFFER_SIZE>::allocate(uint32_t size, uint32_t align)
+	{
+		_p = (char *)memory::align_top(_p, align);
+		if ((int)size > _end - _p) {
+			uint32_t to_allocate = sizeof(void *) + size + align;
+			if (to_allocate < _chunk_size)
+				to_allocate = _chunk_size;
+			_chunk_size *= 2;
+			void *p = _backing.allocate(to_allocate);
+			*(void **)_start = p;
+			_p = _start = (char *)p;
+			_end = _start + to_allocate;
+			*(void **)_start = 0;
+			_p += sizeof(void *);
+			_p = (char *)memory::align_top(_p, align);
+		}
+		void *result = _p;
+		_p += size;
+		return result;
+	}
 } // namespace crown