|
|
@@ -1,7 +1,9 @@
|
|
|
#ifndef ANKI_UTIL_MEMORY_H
|
|
|
#define ANKI_UTIL_MEMORY_H
|
|
|
|
|
|
-#include "anki/util/Allocator.h"
|
|
|
+#include "anki/util/StdTypes.h"
|
|
|
+#include "anki/util/NonCopyable.h"
|
|
|
+#include <atomic>
|
|
|
|
|
|
namespace anki {
|
|
|
|
|
|
@@ -10,132 +12,45 @@ namespace anki {
|
|
|
/// @addtogroup memory
|
|
|
/// @{
|
|
|
|
|
|
-#if 0
|
|
|
-
|
|
|
-/// Function that imitates the new operator. The function allocates memory for
|
|
|
-/// 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
|
|
|
-/// required. The extra chunk is a number that will be used in
|
|
|
-/// deleteObjectArray to identify the number of elements that were allocated
|
|
|
-template<typename T, typename Alloc = Allocator<T>>
|
|
|
-struct New
|
|
|
-{
|
|
|
- PtrSize n; ///< Number of elements
|
|
|
- Alloc alloc; ///< The allocator
|
|
|
-
|
|
|
- New(PtrSize n_ = 1, const Alloc& alloc_ = Alloc())
|
|
|
- : n(n_), alloc(alloc_)
|
|
|
- {}
|
|
|
-
|
|
|
- template<typename... Args>
|
|
|
- T* operator()(Args&&... args)
|
|
|
- {
|
|
|
- ANKI_ASSERT(n != 0);
|
|
|
- T* out;
|
|
|
-
|
|
|
- // If the number of elements is then do a simple allocaton
|
|
|
- if(n == 1)
|
|
|
- {
|
|
|
- out = alloc.allocate(n);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // Allocate a memory block that includes the array size
|
|
|
- typedef typename Alloc::template rebind<U8>::other CharAlloc;
|
|
|
- CharAlloc charAlloc(alloc);
|
|
|
- U8* mem = charAlloc.allocate(sizeof(PtrSize) + n * sizeof(T));
|
|
|
-
|
|
|
- // Set the size of the block
|
|
|
- *(PtrSize*)mem = n;
|
|
|
-
|
|
|
- // Set the output address
|
|
|
- out = (T*)(mem + sizeof(PtrSize));
|
|
|
- }
|
|
|
-
|
|
|
- // Call the constuctors
|
|
|
- for(PtrSize i = 0; i < n; i++)
|
|
|
- {
|
|
|
- alloc.construct(&out[i], std::forward<Args>(args)...);
|
|
|
- }
|
|
|
-
|
|
|
- // Return result
|
|
|
- return out;
|
|
|
- }
|
|
|
-};
|
|
|
-
|
|
|
-/// Function that imitates the delete operator
|
|
|
-template<typename T, typename Alloc = Allocator<T>>
|
|
|
-struct Delete
|
|
|
+/// Thread safe memory pool
|
|
|
+class StackedMemoryPool: public NonCopyable
|
|
|
{
|
|
|
- Alloc alloc;
|
|
|
+public:
|
|
|
+ /// Default constructor
|
|
|
+ StackedMemoryPool(PtrSize size, U32 alignmentBits = 16);
|
|
|
|
|
|
- Delete(const Alloc& alloc_ = Alloc())
|
|
|
- : alloc(alloc_)
|
|
|
- {}
|
|
|
+ /// Move
|
|
|
+ StackedMemoryPool(StackedMemoryPool&& other);
|
|
|
|
|
|
- void operator()(void* ptr)
|
|
|
- {
|
|
|
- T* p = (T*)ptr;
|
|
|
+ ~StackedMemoryPool();
|
|
|
|
|
|
- // Make sure the type is defined
|
|
|
- typedef U8 TypeMustBeComplete[sizeof(T) ? 1 : -1];
|
|
|
- (void) sizeof(TypeMustBeComplete);
|
|
|
+ /// Allocate memory in StackedMemoryPool
|
|
|
+ void* allocate(PtrSize size) throw();
|
|
|
|
|
|
- if(p)
|
|
|
- {
|
|
|
- // Rebind allocator because the Alloc may be of another type
|
|
|
- typename Alloc::template rebind<T>::other alloc(alloc);
|
|
|
+ /// Free memory in StackedMemoryPool
|
|
|
+ Bool free(void* ptr) throw();
|
|
|
|
|
|
- // Call the destructor
|
|
|
- alloc.destroy(p);
|
|
|
+private:
|
|
|
+ /// Allocated memory
|
|
|
+ U8* memory = nullptr;
|
|
|
|
|
|
- // Deallocate
|
|
|
- alloc.deallocate(p, 1);
|
|
|
- }
|
|
|
- }
|
|
|
-};
|
|
|
+ /// Size of the allocated memory
|
|
|
+ PtrSize memsize = 0;
|
|
|
|
|
|
-/// Function that imitates the delete[] operator
|
|
|
-template<typename T, typename Alloc = Allocator<T>>
|
|
|
-struct DeleteArray
|
|
|
-{
|
|
|
- Alloc alloc;
|
|
|
+ /// Points to the memory and more specifically to the address of the next
|
|
|
+ /// allocation
|
|
|
+ std::atomic<U8*> ptr = {nullptr};
|
|
|
|
|
|
- DeleteArray(const Alloc& alloc_ = Alloc())
|
|
|
- : alloc(alloc_)
|
|
|
- {}
|
|
|
+ /// Alignment
|
|
|
+ U32 alignmentBits;
|
|
|
|
|
|
- void operator()(void* ptr)
|
|
|
+ /// Calculate tha aligned size
|
|
|
+ PtrSize calcAlignSize(PtrSize size) const
|
|
|
{
|
|
|
- // Make sure the type is defined
|
|
|
- typedef U8 TypeMustBeComplete[sizeof(T) ? 1 : -1];
|
|
|
- (void) sizeof(TypeMustBeComplete);
|
|
|
-
|
|
|
- T* p = (T*)ptr;
|
|
|
-
|
|
|
- if(p)
|
|
|
- {
|
|
|
- // Get the allocated block
|
|
|
- U8* block = (U8*)(p) - sizeof(PtrSize);
|
|
|
-
|
|
|
- // Get number of elements
|
|
|
- const PtrSize n = *(PtrSize*)block;
|
|
|
-
|
|
|
- // Call the destructors
|
|
|
- for(PtrSize i = 0; i < n; i++)
|
|
|
- {
|
|
|
- alloc.destroy(&p[i]);
|
|
|
- }
|
|
|
-
|
|
|
- // Deallocate the block
|
|
|
- typename Alloc::template rebind<U8>::other allocc(alloc);
|
|
|
- allocc.deallocate(block, n * sizeof(T) + sizeof(PtrSize));
|
|
|
- }
|
|
|
+ return size + (size % (alignmentBits / 8));
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-#endif
|
|
|
-
|
|
|
/// @}
|
|
|
/// @}
|
|
|
|