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>
6{
7 using size_type = std::size_t;
8 using pointer = void*;
9 constexpr uintptr_t AlignUp(const uintptr_t value, const uintptr_t alignment)
10 {
11 return value % alignment ? (value + alignment - value % alignment) : value;
12 }
13 constexpr uintptr_t AlignDown(const uintptr_t value, const uintptr_t alignment)
14 {
15 return value % alignment ? (value - value % alignment) : value;
16 }
29 {
30 public:
31 virtual ~Allocator() = default;
32 virtual pointer Allocate(size_type size, size_t alignment = alignof(std::max_align_t)) noexcept = 0;
33 virtual void Deallocate(pointer ptr) noexcept = 0;
34 virtual pointer Reallocate(pointer ptr, size_type new_size, size_t alignment) noexcept = 0;
35
36 Arena AllocateArena(size_type size, size_t alignment) { return {Allocate(size, alignment), size}; }
37 Arena AllocateArena(size_type size) { return {Allocate(size), size}; }
39 {
40 if (arena.memory)
41 Deallocate(arena.memory);
42 }
43 Allocator* Ptr() { return this; }
44 };
49 {
52 ScopedArena(Allocator* res, size_t size, size_t alignment = alignof(std::max_align_t)) :
53 resource(res), arena(res->AllocateArena(size, alignment)) {};
55 constexpr operator Arena() const { return arena; }
56 constexpr operator bool() const noexcept { return arena.memory != nullptr; }
57 };
58 constexpr size_t kDefaultStackArenaSize = 12 * 1024; // 12 KiB
62 template <size_t Size = kDefaultStackArenaSize>
64 {
65 alignas(std::max_align_t) std::byte data[Size];
66 constexpr operator Arena() { return {reinterpret_cast<void*>(data), Size}; }
67 constexpr operator Arena() const { return {reinterpret_cast<void*>(data), Size}; }
68 };
69
85 template <typename T = void>
87 {
88 using value_type = T;
89 using size_type = std::size_t;
90 using difference_type = std::ptrdiff_t;
91 using pointer = T*;
92 using const_pointer = const T*;
93 using reference = T&;
94 using const_reference = const T&;
95
97
98 template <typename U>
99 friend struct StlAllocator; // Rebind ctor
100 template <typename U>
101 struct Rebind
102 {
104 };
105 StlAllocator(Allocator* resource) noexcept : mResource(resource) {}
106 template <typename U>
107 StlAllocator(const StlAllocator<U>& other) noexcept : mResource(other.mResource)
108 {
109 }
110
112 {
113 return static_cast<pointer>(mResource->Allocate(n * sizeof(T), alignof(T)));
114 }
115 void deallocate(pointer p, size_type n) noexcept { mResource->Deallocate(p); }
116 void deallocate(pointer p) noexcept { mResource->Deallocate(p); }
117 // Allocators are deemed equal if they point to the same resource
118 friend bool operator==(const StlAllocator& lhs, const StlAllocator& rhs) noexcept
119 {
120 return lhs.mResource == rhs.mResource;
121 }
122 friend bool operator!=(const StlAllocator& lhs, const StlAllocator& rhs) noexcept { return !(lhs == rhs); }
123 };
124
129 template <typename T>
131 {
133 void operator()(T* ptr) noexcept
134 {
135 if (ptr && mResource)
136 {
137 std::destroy_at(ptr);
138 mResource->Deallocate(ptr);
139 }
140 }
141 };
148 template <typename Base, typename Derived, typename... Args>
149 Base* ConstructBase(Allocator* resource, Args&&... args)
150 {
151 auto raw = resource->Allocate(sizeof(Derived), alignof(Derived));
152 return std::construct_at(static_cast<Derived*>(raw), std::forward<Args>(args)...);
153 }
159 template <typename T, typename... Args>
160 T* Construct(Allocator* resource, Args&&... args)
161 {
162 return ConstructBase<T, T>(resource, std::forward<Args>(args)...);
163 }
167 template <typename T>
168 void Destruct(Allocator* resource, T* obj)
169 {
170 StlDeleter<T> deleter(resource);
171 deleter(obj);
172 }
179 template <typename T, typename Deleter = StlDeleter<T>>
180 using UniquePtr = std::unique_ptr<T, Deleter>;
181
188 template <typename Base, typename Derived, typename... Args>
190 {
191 Base* obj = ConstructBase<Base, Derived>(resource, std::forward<Args>(args)...);
192 return UniquePtr<Base>(obj, StlDeleter<Base>{resource});
193 }
199 template <typename T, typename... Args>
200 UniquePtr<T> ConstructUnique(Allocator* resource, Args&&... args)
201 {
202 return ConstructUniqueBase<T, T>(resource, std::forward<Args>(args)...);
203 }
204
208 template <typename T>
209 using SharedPtr = std::shared_ptr<T>;
210 template <typename T>
211 using WeakPtr = std::weak_ptr<T>;
212
219 template <typename Base, typename Derived, typename... Args>
221 {
222 return std::allocate_shared<Derived>(StlAllocator<Derived>{resource}, std::forward<Args>(args)...);
223 }
224
230 template <typename T, typename... Args>
231 SharedPtr<T> ConstructShared(Allocator* resource, Args&&... args)
232 {
233 return ConstructSharedBase<T, T>(resource, std::forward<Args>(args)...);
234 }
235
237 extern Allocator* GetGlobalAllocator();
238} // namespace Foundation::Core
239
240#define GLOBAL_ALLOC Foundation::Core::GetGlobalAllocator()
241namespace Foundation::Core
242{
243 // Default allocator for STL containers to be constructed with @ref GLOBAL_ALLOC
244 template <typename T = void>
246 {
247 using value_type = T;
248 using size_type = std::size_t;
249 using difference_type = std::ptrdiff_t;
250 using pointer = T*;
251 using const_pointer = const T*;
252 using reference = T&;
253 using const_reference = const T&;
254 StlDefaultAllocator() noexcept = default;
256 template <typename U>
257 constexpr StlDefaultAllocator(const StlDefaultAllocator<U>&) noexcept
258 {
259 }
260
262 {
263 return static_cast<pointer>(GLOBAL_ALLOC->Allocate(n * sizeof(T), alignof(T)));
264 }
265 void deallocate(pointer p, size_type n) noexcept { GLOBAL_ALLOC->Deallocate(p); }
266 void deallocate(pointer p) noexcept { GLOBAL_ALLOC->Deallocate(p); }
267 friend bool operator==(const StlDefaultAllocator& lhs, const StlDefaultAllocator& rhs) noexcept { return true; }
268 friend bool operator!=(const StlDefaultAllocator& lhs, const StlDefaultAllocator& rhs) noexcept
269 {
270 return false;
271 }
272 };
273
274} // namespace Foundation::Core
#define GLOBAL_ALLOC
Definition Allocator.hpp:240
Allocator interface (noexcept)
Definition Allocator.hpp:29
Arena AllocateArena(size_type size)
Definition Allocator.hpp:37
virtual ~Allocator()=default
virtual void Deallocate(pointer ptr) noexcept=0
virtual pointer Allocate(size_type size, size_t alignment=alignof(std::max_align_t)) noexcept=0
Arena AllocateArena(size_type size, size_t alignment)
Definition Allocator.hpp:36
virtual pointer Reallocate(pointer ptr, size_type new_size, size_t alignment) noexcept=0
void DeallocateArena(Arena arena)
Definition Allocator.hpp:38
Allocator * Ptr()
Definition Allocator.hpp:43
Lock-free atomic primitives and implementations of data structures.
Definition Allocator.hpp:6
std::size_t size_type
Definition Allocator.hpp:7
std::weak_ptr< T > WeakPtr
Definition Allocator.hpp:211
Allocator * GetGlobalAllocator()
Definition AllocatorHeap.cpp:70
constexpr uintptr_t AlignUp(const uintptr_t value, const uintptr_t alignment)
Definition Allocator.hpp:9
constexpr size_t kDefaultStackArenaSize
Definition Allocator.hpp:58
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:149
constexpr uintptr_t AlignDown(const uintptr_t value, const uintptr_t alignment)
Definition Allocator.hpp:13
void Destruct(Allocator *resource, T *obj)
Convenience destructor for objects allocated with Construct or ConstructBase.
Definition Allocator.hpp:168
std::shared_ptr< T > SharedPtr
std::shared_ptr with custom deleter that uses a Foundation::Core::Allocator to deallocate memory.
Definition Allocator.hpp:209
T * Construct(Allocator *resource, Args &&... args)
Convenience placement new with object of type T using a Foundation::Core::Allocator.
Definition Allocator.hpp:160
void * pointer
Definition Allocator.hpp:8
SharedPtr< T > ConstructShared(Allocator *resource, Args &&... args)
Convenience wrapper for calling ConstructSharedBase when Base and Derived are the same type.
Definition Allocator.hpp:231
UniquePtr< T > ConstructUnique(Allocator *resource, Args &&... args)
Convenience wrapper for calling ConstructUniqueBase when Base and Derived are the same type.
Definition Allocator.hpp:200
std::unique_ptr< T, Deleter > UniquePtr
std::unique_ptr with custom deleter that uses a Foundation::Core::Allocator to deallocate memory.
Definition Allocator.hpp:180
SharedPtr< Base > ConstructSharedBase(Allocator *resource, Args &&... args)
Helper function for constructing a ref-counted resource with a Foundation::Core::Allocator.
Definition Allocator.hpp:220
UniquePtr< Base > ConstructUniqueBase(Allocator *resource, Args &&... args)
Helper function for constructing a pinned resource with a Foundation::Core::Allocator.
Definition Allocator.hpp:189
A memory arena allocated from an Allocator.
Definition Allocator.hpp:21
size_type size
Definition Allocator.hpp:23
pointer memory
Definition Allocator.hpp:22
RAII wrapper for an arena allocated from an Allocator.
Definition Allocator.hpp:49
Allocator * resource
Definition Allocator.hpp:50
Arena arena
Definition Allocator.hpp:51
~ScopedArena()
Definition Allocator.hpp:54
ScopedArena(Allocator *res, size_t size, size_t alignment=alignof(std::max_align_t))
Definition Allocator.hpp:52
A fixed-size stack memory arena.
Definition Allocator.hpp:64
std::byte data[Size]
Definition Allocator.hpp:65
Definition Allocator.hpp:102
std::allocator adaptor for Foundation::Core::Allocator
Definition Allocator.hpp:87
StlAllocator(const StlAllocator< U > &other) noexcept
Definition Allocator.hpp:107
StlAllocator(Allocator *resource) noexcept
Definition Allocator.hpp:105
friend bool operator==(const StlAllocator &lhs, const StlAllocator &rhs) noexcept
Definition Allocator.hpp:118
T & reference
Definition Allocator.hpp:93
void deallocate(pointer p, size_type n) noexcept
Definition Allocator.hpp:115
const T * const_pointer
Definition Allocator.hpp:92
friend bool operator!=(const StlAllocator &lhs, const StlAllocator &rhs) noexcept
Definition Allocator.hpp:122
Allocator * mResource
Definition Allocator.hpp:96
std::size_t size_type
Definition Allocator.hpp:89
void deallocate(pointer p) noexcept
Definition Allocator.hpp:116
T * pointer
Definition Allocator.hpp:91
pointer allocate(size_type n) noexcept
Definition Allocator.hpp:111
std::ptrdiff_t difference_type
Definition Allocator.hpp:90
const T & const_reference
Definition Allocator.hpp:94
T value_type
Definition Allocator.hpp:88
Definition Allocator.hpp:246
T value_type
Definition Allocator.hpp:247
friend bool operator!=(const StlDefaultAllocator &lhs, const StlDefaultAllocator &rhs) noexcept
Definition Allocator.hpp:268
T * pointer
Definition Allocator.hpp:250
const T * const_pointer
Definition Allocator.hpp:251
std::ptrdiff_t difference_type
Definition Allocator.hpp:249
T & reference
Definition Allocator.hpp:252
void deallocate(pointer p, size_type n) noexcept
Definition Allocator.hpp:265
friend bool operator==(const StlDefaultAllocator &lhs, const StlDefaultAllocator &rhs) noexcept
Definition Allocator.hpp:267
const T & const_reference
Definition Allocator.hpp:253
std::size_t size_type
Definition Allocator.hpp:248
pointer allocate(size_type n) noexcept
Definition Allocator.hpp:261
void deallocate(pointer p) noexcept
Definition Allocator.hpp:266
Custom deleter for Foundation::Core::UniquePtr and Foundation::Core::SharedPtr that uses a Foundation...
Definition Allocator.hpp:131
Allocator * mResource
Definition Allocator.hpp:132
void operator()(T *ptr) noexcept
Definition Allocator.hpp:133