Gaia-ECS v0.9.3
A simple and powerful entity component system
Loading...
Searching...
No Matches
mem_alloc.h
1#pragma once
2#include "gaia/config/config.h"
3#include "gaia/config/profiler.h"
4
5#include <cstdint>
6#include <cstring>
7#include <stdlib.h>
8#include <type_traits>
9#include <utility>
10
11#if GAIA_PLATFORM_WINDOWS
12 #define GAIA_MEM_ALLC(size) ::malloc(size)
13 #define GAIA_MEM_FREE(ptr) ::free(ptr)
14
15 // Clang with MSVC codegen needs some remapping
16 #if !defined(aligned_alloc)
17 #define GAIA_MEM_ALLC_A(size, alig) ::_aligned_malloc(size, alig)
18 #define GAIA_MEM_FREE_A(ptr) ::_aligned_free(ptr)
19 #else
20 #define GAIA_MEM_ALLC_A(size, alig) ::aligned_alloc(alig, size)
21 #define GAIA_MEM_FREE_A(ptr) ::aligned_free(ptr)
22 #endif
23#else
24 #define GAIA_MEM_ALLC(size) ::malloc(size)
25 #define GAIA_MEM_ALLC_A(size, alig) ::aligned_alloc(alig, size)
26 #define GAIA_MEM_FREE(ptr) ::free(ptr)
27 #define GAIA_MEM_FREE_A(ptr) ::free(ptr)
28#endif
29
30namespace gaia {
31 namespace mem {
33 GAIA_NODISCARD static void* alloc(size_t size) {
34 GAIA_ASSERT(size > 0);
35
36 void* ptr = GAIA_MEM_ALLC(size);
37 GAIA_ASSERT(ptr != nullptr);
38 GAIA_PROF_ALLOC(ptr, size);
39 return ptr;
40 }
41
42 GAIA_NODISCARD static void* alloc([[maybe_unused]] const char* name, size_t size) {
43 GAIA_ASSERT(size > 0);
44
45 void* ptr = GAIA_MEM_ALLC(size);
46 GAIA_ASSERT(ptr != nullptr);
47 GAIA_PROF_ALLOC2(ptr, size, name);
48 return ptr;
49 }
50
51 GAIA_NODISCARD static void* alloc_alig(size_t size, size_t alig) {
52 GAIA_ASSERT(size > 0);
53 GAIA_ASSERT(alig > 0);
54
55 // Make sure size is a multiple of the alignment
56 size = (size + alig - 1) & ~(alig - 1);
57 void* ptr = GAIA_MEM_ALLC_A(size, alig);
58 GAIA_ASSERT(ptr != nullptr);
59 GAIA_PROF_ALLOC(ptr, size);
60 return ptr;
61 }
62
63 GAIA_NODISCARD static void* alloc_alig([[maybe_unused]] const char* name, size_t size, size_t alig) {
64 GAIA_ASSERT(size > 0);
65 GAIA_ASSERT(alig > 0);
66
67 // Make sure size is a multiple of the alignment
68 size = (size + alig - 1) & ~(alig - 1);
69 void* ptr = GAIA_MEM_ALLC_A(size, alig);
70 GAIA_ASSERT(ptr != nullptr);
71 GAIA_PROF_ALLOC2(ptr, size, name);
72 return ptr;
73 }
74
75 static void free(void* ptr) {
76 GAIA_ASSERT(ptr != nullptr);
77
78 GAIA_MEM_FREE(ptr);
79 GAIA_PROF_FREE(ptr);
80 }
81
82 static void free([[maybe_unused]] const char* name, void* ptr) {
83 GAIA_ASSERT(ptr != nullptr);
84
85 GAIA_MEM_FREE(ptr);
86 GAIA_PROF_FREE2(ptr, name);
87 }
88
89 static void free_alig(void* ptr) {
90 GAIA_ASSERT(ptr != nullptr);
91
92 GAIA_MEM_FREE_A(ptr);
93 GAIA_PROF_FREE(ptr);
94 }
95
96 static void free_alig([[maybe_unused]] const char* name, void* ptr) {
97 GAIA_ASSERT(ptr != nullptr);
98
99 GAIA_MEM_FREE_A(ptr);
100 GAIA_PROF_FREE2(ptr, name);
101 }
102 };
103
105 static DefaultAllocator& get() {
106 static DefaultAllocator s_allocator;
107 return s_allocator;
108 }
109 };
110
111 struct AllocHelper {
112 template <typename T, typename Adaptor = DefaultAllocatorAdaptor>
113 GAIA_NODISCARD static T* alloc(uint32_t cnt = 1) {
114 return (T*)Adaptor::get().alloc(sizeof(T) * cnt);
115 }
116 template <typename T, typename Adaptor = DefaultAllocatorAdaptor>
117 GAIA_NODISCARD static T* alloc(const char* name, uint32_t cnt = 1) {
118 return (T*)Adaptor::get().alloc(name, sizeof(T) * cnt);
119 }
120 template <typename T, typename Adaptor = DefaultAllocatorAdaptor>
121 GAIA_NODISCARD static T* alloc_alig(size_t alig, uint32_t cnt = 1) {
122 return (T*)Adaptor::get().alloc_alig(sizeof(T) * cnt, alig);
123 }
124 template <typename T, typename Adaptor = DefaultAllocatorAdaptor>
125 GAIA_NODISCARD static T* alloc_alig(const char* name, size_t alig, uint32_t cnt = 1) {
126 return (T*)Adaptor::get().alloc_alig(name, sizeof(T) * cnt, alig);
127 }
128 template <typename Adaptor = DefaultAllocatorAdaptor>
129 static void free(void* ptr) {
130 Adaptor::get().free(ptr);
131 }
132 template <typename Adaptor = DefaultAllocatorAdaptor>
133 static void free(const char* name, void* ptr) {
134 Adaptor::get().free(name, ptr);
135 }
136 template <typename Adaptor = DefaultAllocatorAdaptor>
137 static void free_alig(void* ptr) {
138 Adaptor::get().free_alig(ptr);
139 }
140 template <typename Adaptor = DefaultAllocatorAdaptor>
141 static void free_alig(const char* name, void* ptr) {
142 Adaptor::get().free_alig(name, ptr);
143 }
144 };
145
148 GAIA_NODISCARD inline void* mem_alloc(size_t size) {
149 return DefaultAllocatorAdaptor::get().alloc(size);
150 }
151
155 GAIA_NODISCARD inline void* mem_alloc(const char* name, size_t size) {
156 return DefaultAllocatorAdaptor::get().alloc(name, size);
157 }
158
163 GAIA_NODISCARD inline void* mem_alloc_alig(size_t size, size_t alig) {
164 return DefaultAllocatorAdaptor::get().alloc_alig(size, alig);
165 }
166
172 GAIA_NODISCARD inline void* mem_alloc_alig(const char* name, size_t size, size_t alig) {
173 return DefaultAllocatorAdaptor::get().alloc_alig(name, size, alig);
174 }
175
178 inline void mem_free(void* ptr) {
179 DefaultAllocatorAdaptor::get().free(ptr);
180 }
181
185 inline void mem_free(const char* name, void* ptr) {
186 DefaultAllocatorAdaptor::get().free(name, ptr);
187 }
188
191 inline void mem_free_alig(void* ptr) {
192 DefaultAllocatorAdaptor::get().free_alig(ptr);
193 }
194
198 inline void mem_free_alig(const char* name, void* ptr) {
199 DefaultAllocatorAdaptor::get().free_alig(name, ptr);
200 }
201
206 template <typename T, typename V>
207 GAIA_NODISCARD constexpr T align(T num, V alignment) {
208 return alignment == 0 ? num : ((num + (alignment - 1)) / alignment) * alignment;
209 }
210
216 template <size_t alignment, typename T>
217 GAIA_NODISCARD constexpr T align(T num) {
218 return ((num + (alignment - 1)) & ~(alignment - 1));
219 }
220
225 template <typename T, typename V>
226 GAIA_NODISCARD constexpr uint32_t padding(T num, V alignment) {
227 return (uint32_t)(align(num, alignment) - num);
228 }
229
234 template <size_t alignment, typename T>
235 GAIA_NODISCARD constexpr uint32_t padding(T num) {
236 return (uint32_t)(align<alignment>(num) - num);
237 }
238
244 template <typename Dst, typename Src>
245 GAIA_NODISCARD Dst bit_cast(const Src& src) {
246 static_assert(sizeof(Dst) == sizeof(Src));
247 static_assert(std::is_trivially_copyable_v<Src>);
248 static_assert(std::is_trivially_copyable_v<Dst>);
249
250 // int i = {};
251 // float f = *(*float)&i; // undefined behavior
252 // memcpy(&f, &i, sizeof(float)); // okay
253 Dst dst;
254 memmove((void*)&dst, (const void*)&src, sizeof(Dst));
255 return dst;
256 }
257
259 template <typename T>
261 void* m_p;
262
263 public:
264 unaligned_ref(void* p): m_p(p) {}
265
266 unaligned_ref& operator=(const T& value) {
267 memmove(m_p, (const void*)&value, sizeof(T));
268 return *this;
269 }
270
271 GAIA_NODISCARD operator T() const {
272 T tmp;
273 memmove((void*)&tmp, (const void*)m_p, sizeof(T));
274 return tmp;
275 }
276 };
277 } // namespace mem
278} // namespace gaia
Pointer wrapper for writing memory in defined way (not causing undefined behavior)
Definition mem_alloc.h:260
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9
Definition mem_alloc.h:111
Definition mem_alloc.h:104
Definition mem_alloc.h:32