Foundation
Loading...
Searching...
No Matches
Allocator.hpp
Go to the documentation of this file.
1#pragma once
2#include <atomic>
3#include <memory>
4#include <stdexcept>
5namespace Foundation::Core {
6 using size_type = std::size_t;
7 using pointer = void*;
8 constexpr uintptr_t AlignUp(const uintptr_t value, const uintptr_t alignment) {
9 return value % alignment ? (value + alignment - value % alignment) : value;
10 }
11 constexpr uintptr_t AlignDown(const uintptr_t value, const uintptr_t alignment) {
12 return value % alignment ? (value - value % alignment) : value;
13 }
24 class Allocator {
25 public:
26 virtual ~Allocator() = default;
27 virtual pointer Allocate(size_type size, size_t alignment = alignof(std::max_align_t)) = 0;
28 virtual void Deallocate(pointer ptr) = 0;
30
31 virtual void QueryBudget(size_t& used, size_t& budget) const = 0;
32
33 Arena AllocateArena(size_type size, size_t alignment) { return { Allocate(size, alignment), size }; }
34 Arena AllocateArena(size_type size) { return { Allocate(size), size }; }
35 void DeallocateArena(Arena arena) {
36 if (arena.memory)
37 Deallocate(arena.memory);
38 }
39 Allocator* Ptr() { return this; }
40 };
44 struct ScopedArena {
47 ScopedArena(Allocator* res, size_t size, size_t alignment = alignof(std::max_align_t)) :
48 resource(res), arena(res->AllocateArena(size, alignment)) {};
50 constexpr operator Arena() const { return arena; }
51 constexpr operator bool() const noexcept { return arena.memory != nullptr; }
52 };
53 constexpr size_t kDefaultStackArenaSize = 12 * 1024; // 12 KiB
57 template<size_t Size = kDefaultStackArenaSize> struct StackArena {
58 alignas(std::max_align_t) std::byte data[Size];
59 constexpr operator Arena() { return { reinterpret_cast<void*>(data), Size }; }
60 constexpr operator Arena() const { return { reinterpret_cast<void*>(data), Size }; }
61 };
62
77 template <typename T = void>
78 struct StlAllocator {
79 using value_type = T;
80 using size_type = std::size_t;
81 using difference_type = std::ptrdiff_t;
82 using pointer = T*;
83 using const_pointer = const T*;
84 using reference = T&;
85 using const_reference = const T&;
86
88
89 template<typename U> friend struct StlAllocator; // Rebind ctor
90 template<typename U> struct Rebind { using other = StlAllocator<U>; };
91 StlAllocator(Allocator* resource) noexcept : mResource(resource) {}
92 template<typename U>
93 StlAllocator(const StlAllocator<U>& other) noexcept : mResource(other.mResource) {}
94
96 return static_cast<pointer>(mResource->Allocate(n * sizeof(T), alignof(T)));
97 }
98 void deallocate(pointer p, size_type n) noexcept {
100 }
101 void deallocate(pointer p) noexcept {
102 mResource->Deallocate(p, sizeof(T));
103 }
104 // Allocators are deemed equal if they point to the same resource
105 friend bool operator==(const StlAllocator& lhs, const StlAllocator& rhs) noexcept {
106 return lhs.mResource == rhs.mResource;
107 }
108 friend bool operator!=(const StlAllocator& lhs, const StlAllocator& rhs) noexcept {
109 return !(lhs == rhs);
110 }
111 };
112
116 template <typename T>
117 struct StlDeleter {
119 void operator()(T* ptr) noexcept {
120 if (ptr) {
121 std::destroy_at(ptr);
122 mResource->Deallocate(ptr);
123 }
124 }
125 };
131 template <typename Base, typename Derived, typename ...Args>
133 auto raw = resource->Allocate(sizeof(Derived), alignof(Derived));
134 try {
135 Derived* obj = std::construct_at(static_cast<Derived*>(raw), std::forward<Args>(args)...);
136 return obj;
137 }
138 catch (...) {
139 resource->Deallocate(raw);
140 throw;
141 }
142 }
148 template <typename T, typename ...Args>
149 T* Construct(Allocator* resource, Args&& ...args) {
150 return ConstructBase<T, T>(resource, std::forward<Args>(args)...);
151 }
155 template <typename T>
156 void Destruct(Allocator* resource, T* obj) {
157 StlDeleter<T> deleter(resource);
158 deleter(obj);
159 }
165 template<typename T, typename Deleter = StlDeleter<T>>
166 using UniquePtr = std::unique_ptr<T, Deleter>;
167
174 template <typename Base, typename Derived, typename ...Args>
176 Base* obj = ConstructBase<Base, Derived>(resource, std::forward<Args>(args)...);
177 return UniquePtr<Base>(obj, StlDeleter<Base>{ resource });
178 }
184 template <typename T, typename ...Args>
186 return ConstructUniqueBase<T, T>(resource, std::forward<Args>(args)...);
187 }
188
192 template<typename T>
193 using SharedPtr = std::shared_ptr<T>;
194
201 template<typename Base, typename Derived, typename ...Args>
203 Base* obj = ConstructBase<Base, Derived>(resource, std::forward<Args>(args)...);
204 return { obj, StlDeleter<Base>{ resource } };
205 }
206
212 template <typename T, typename ...Args>
214 return ConstructSharedBase<T, T>(resource, std::forward<Args>(args)...);
215 }
216
218 extern Allocator* getGlobalAllocator();
219}
220
221#define GLOBAL_ALLOC Foundation::Core::getGlobalAllocator()
General Purpose Allocator (GPA) interface.
Definition Allocator.hpp:24
Arena AllocateArena(size_type size)
Definition Allocator.hpp:34
virtual pointer Reallocate(pointer ptr, size_type new_size, size_t alignment)=0
virtual ~Allocator()=default
virtual void QueryBudget(size_t &used, size_t &budget) const =0
virtual void Deallocate(pointer ptr)=0
Arena AllocateArena(size_type size, size_t alignment)
Definition Allocator.hpp:33
void DeallocateArena(Arena arena)
Definition Allocator.hpp:35
Allocator * Ptr()
Definition Allocator.hpp:39
virtual pointer Allocate(size_type size, size_t alignment=alignof(std::max_align_t))=0
Lock-free atomic primitives and implementations of data structures.
Definition Allocator.hpp:5
std::size_t size_type
Definition Allocator.hpp:6
SharedPtr< T > ConstructShared(Allocator *resource, Args &&...args)
Convenience wrapper for calling ConstructSharedBase when Base and Derived are the same type.
Definition Allocator.hpp:213
UniquePtr< T > ConstructUnique(Allocator *resource, Args &&...args)
Convenience wrapper for calling ConstructUniqueBase when Base and Derived are the same type.
Definition Allocator.hpp:185
Allocator * getGlobalAllocator()
Definition AllocatorHeap.cpp:47
UniquePtr< Base > ConstructUniqueBase(Allocator *resource, Args &&...args)
Helper function for constructing a pinned resource with a Foundation::Core::Allocator.
Definition Allocator.hpp:175
constexpr uintptr_t AlignUp(const uintptr_t value, const uintptr_t alignment)
Definition Allocator.hpp:8
constexpr size_t kDefaultStackArenaSize
Definition Allocator.hpp:53
constexpr uintptr_t AlignDown(const uintptr_t value, const uintptr_t alignment)
Definition Allocator.hpp:11
void Destruct(Allocator *resource, T *obj)
Convenience destructor for objects allocated with Construct or ConstructBase.
Definition Allocator.hpp:156
std::shared_ptr< T > SharedPtr
std::shared_ptr with custom deleter that uses a Foundation::Core::Allocator to deallocate memory.
Definition Allocator.hpp:193
void * pointer
Definition Allocator.hpp:7
Base * ConstructBase(Allocator *resource, Args &&...args)
Placement new helper for constructing an object of type Derived (which can be a subclass of Base) usi...
Definition Allocator.hpp:132
std::unique_ptr< T, Deleter > UniquePtr
std::unique_ptr with custom deleter that uses a Foundation::Core::Allocator to deallocate memory.
Definition Allocator.hpp:166
SharedPtr< Base > ConstructSharedBase(Allocator *resource, Args &&...args)
Helper function for constructing a ref-counted resource with a Foundation::Core::Allocator.
Definition Allocator.hpp:202
T * Construct(Allocator *resource, Args &&...args)
Convenience placement new with object of type T using a Foundation::Core::Allocator.
Definition Allocator.hpp:149
A memory arena allocated from an Allocator.
Definition Allocator.hpp:17
size_type size
Definition Allocator.hpp:19
pointer memory
Definition Allocator.hpp:18
RAII wrapper for an arena allocated from an Allocator.
Definition Allocator.hpp:44
Allocator * resource
Definition Allocator.hpp:45
Arena arena
Definition Allocator.hpp:46
~ScopedArena()
Definition Allocator.hpp:49
ScopedArena(Allocator *res, size_t size, size_t alignment=alignof(std::max_align_t))
Definition Allocator.hpp:47
A fixed-size stack memory arena.
Definition Allocator.hpp:57
std::byte data[Size]
Definition Allocator.hpp:58
Definition Allocator.hpp:90
std::allocator adaptor for Foundation::Core::Allocator
Definition Allocator.hpp:78
StlAllocator(const StlAllocator< U > &other) noexcept
Definition Allocator.hpp:93
StlAllocator(Allocator *resource) noexcept
Definition Allocator.hpp:91
friend bool operator==(const StlAllocator &lhs, const StlAllocator &rhs) noexcept
Definition Allocator.hpp:105
T & reference
Definition Allocator.hpp:84
void deallocate(pointer p, size_type n) noexcept
Definition Allocator.hpp:98
const T * const_pointer
Definition Allocator.hpp:83
friend bool operator!=(const StlAllocator &lhs, const StlAllocator &rhs) noexcept
Definition Allocator.hpp:108
pointer allocate(size_type n)
Definition Allocator.hpp:95
Allocator * mResource
Definition Allocator.hpp:87
std::size_t size_type
Definition Allocator.hpp:80
void deallocate(pointer p) noexcept
Definition Allocator.hpp:101
T * pointer
Definition Allocator.hpp:82
std::ptrdiff_t difference_type
Definition Allocator.hpp:81
const T & const_reference
Definition Allocator.hpp:85
T value_type
Definition Allocator.hpp:79
Custom deleter for Foundation::Core::UniquePtr and Foundation::Core::SharedPtr that uses a Foundation...
Definition Allocator.hpp:117
Allocator * mResource
Definition Allocator.hpp:118
void operator()(T *ptr) noexcept
Definition Allocator.hpp:119