NexusForce 1.0.0
A rigorously engineered full-stack C++ backend library.
载入中...
搜索中...
未找到
standard_allocator.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_MEMORY_STANDARD_ALLOCATOR_HPP__
2#define NEFORCE_CORE_MEMORY_STANDARD_ALLOCATOR_HPP__
3
11
12#include <new>
15NEFORCE_BEGIN_NAMESPACE__
16
22
29NEFORCE_INLINE17 constexpr size_t MEMORY_ALIGN_THRESHHOLD = 16;
30
37NEFORCE_INLINE17 constexpr size_t MEMORY_BIG_ALLOC_THRESHHOLD = 4096;
38
40NEFORCE_BEGIN_INNER__
41
46using alloc_size_t =
48#ifdef NEFORCE_COMPILER_GCC
50#else
51 size_t;
52#endif
54
55
56#ifdef NEFORCE_COMPILER_MSVC
57
64NEFORCE_INLINE17 constexpr size_t MEMORY_BIG_ALLOC_ALIGN = 32;
65
72NEFORCE_INLINE17 constexpr size_t MEMORY_NO_USER_SIZE = sizeof(void*) + MEMORY_BIG_ALLOC_ALIGN -
73 static_cast<size_t>(1)
74# ifdef NEFORCE_STATE_DEBUG
75 * static_cast<size_t>(2)
76# endif
77 ;
78
85NEFORCE_INLINE17 constexpr size_t MEMORY_BIG_ALLOC_SENTINEL =
86# ifdef NEFORCE_ARCH_BITS_64
87 0xFAFAFAFAFAFAFAFAUL;
88# else
89 0xFAFAFAFAUL;
90# endif
91
92#endif // NEFORCE_COMPILER_MSVC
93
94
103template <size_t Align>
104NEFORCE_ALLOC_OPTIMIZE NEFORCE_CONSTEXPR20 void* __allocate_aux(const alloc_size_t bytes) {
105#ifdef NEFORCE_COMPILER_MSVC
106 if (bytes >= MEMORY_BIG_ALLOC_THRESHHOLD) {
107 const size_t block_size = MEMORY_NO_USER_SIZE + bytes;
108 if (block_size <= bytes) {
109 NEFORCE_THROW_EXCEPTION(memory_exception("invalid block size."));
110 }
111 const auto holder = reinterpret_cast<uintptr_t>(operator new(block_size));
112 NEFORCE_DEBUG_VERIFY(holder != 0, "invalid argument");
113 auto* const ptr = reinterpret_cast<void*>((holder + MEMORY_NO_USER_SIZE) & ~(MEMORY_BIG_ALLOC_ALIGN - 1));
114 static_cast<uintptr_t*>(ptr)[-1] = holder;
115# ifdef NEFORCE_STATE_DEBUG
116 static_cast<uintptr_t*>(ptr)[-2] = MEMORY_BIG_ALLOC_SENTINEL;
117# endif
118 return ptr;
119 }
120#endif
121 return operator new(bytes);
122}
123
124#ifdef NEFORCE_STANDARD_17
125
134template <size_t Align, enable_if_t<(Align > MEMORY_ALIGN_THRESHHOLD), int> = 0>
135NEFORCE_ALLOC_OPTIMIZE NEFORCE_CONSTEXPR20 void* __allocate_dispatch(const alloc_size_t bytes) {
136 size_t align = Align;
137# ifdef NEFORCE_COMPILER_MSVC
138 if (bytes >= MEMORY_BIG_ALLOC_THRESHHOLD) {
139 align = Align > MEMORY_BIG_ALLOC_ALIGN ? Align : MEMORY_BIG_ALLOC_ALIGN;
140 }
141# endif
142# if defined(NEFORCE_COMPILER_CLANG) && defined(NEFORCE_STANDARD_20)
143 if (_NEFORCE is_constant_evaluated()) {
144 return operator new(bytes);
145 }
146# endif
147 return operator new(bytes, std::align_val_t{align});
148}
149
158template <size_t Align, enable_if_t<Align <= MEMORY_ALIGN_THRESHHOLD, int> = 0>
159NEFORCE_ALLOC_OPTIMIZE NEFORCE_CONSTEXPR20 void* __allocate_dispatch(const alloc_size_t bytes) {
160 return inner::__allocate_aux<Align>(bytes);
161}
162
163#endif
164
165NEFORCE_END_INNER__
167
176template <size_t Align>
177NEFORCE_ALLOC_OPTIMIZE NEFORCE_CONSTEXPR20 void* allocate(const inner::alloc_size_t bytes) {
178 if (bytes == 0) {
179 return nullptr;
180 }
181#ifdef NEFORCE_STANDARD_20
182 if (_NEFORCE is_constant_evaluated()) {
183 return operator new(bytes);
184 }
185#endif // NEFORCE_STANDARD_20
186
187#ifdef NEFORCE_STANDARD_17
188 return inner::__allocate_dispatch<Align>(bytes);
189#else
190 return inner::__allocate_aux<Align>(bytes);
191#endif // NEFORCE_STANDARD_17
192}
193
194
196NEFORCE_BEGIN_INNER__
197
206template <size_t Align>
207void __deallocate_aux(void*& ptr, inner::alloc_size_t& bytes) noexcept {
208#ifdef NEFORCE_COMPILER_MSVC
209 if (bytes >= MEMORY_BIG_ALLOC_THRESHHOLD) {
210 bytes += MEMORY_NO_USER_SIZE;
211 const uintptr_t* const user_ptr = static_cast<uintptr_t*>(ptr);
212 const uintptr_t holder = user_ptr[-1];
213 NEFORCE_DEBUG_VERIFY(user_ptr[-2] == MEMORY_BIG_ALLOC_SENTINEL, "invalid sentinel.");
214# ifdef NEFORCE_STATE_DEBUG
215 constexpr uintptr_t min_shift = 2 * sizeof(void*);
216# else
217 constexpr uintptr_t min_shift = sizeof(void*);
218# endif
219 const uintptr_t shift = reinterpret_cast<uintptr_t>(ptr) - holder;
220 NEFORCE_DEBUG_VERIFY(shift >= min_shift && shift <= MEMORY_NO_USER_SIZE, "invalid argument.");
221 ptr = reinterpret_cast<void*>(holder);
222 }
223#endif
224#if defined(NEFORCE_STANDARD_14) && defined(NEFORCE_COMPILER_MSVC)
225 operator delete(ptr, bytes);
226#else
227 operator delete(ptr);
228#endif
229}
230
231#ifdef NEFORCE_STANDARD_17
232
241template <size_t Align, enable_if_t<(Align > MEMORY_ALIGN_THRESHHOLD), int> = 0>
242NEFORCE_CONSTEXPR20 void __deallocate_dispatch(void*& ptr, inner::alloc_size_t& bytes) noexcept {
243 size_t align = Align;
244# ifdef NEFORCE_COMPILER_MSVC
245 if (bytes > MEMORY_BIG_ALLOC_THRESHHOLD) {
246 align = Align > MEMORY_BIG_ALLOC_ALIGN ? Align : MEMORY_BIG_ALLOC_ALIGN;
247 }
248# endif
249# if defined(NEFORCE_STANDARD_14) && defined(NEFORCE_COMPILER_MSVC)
250 operator delete(ptr, bytes, std::align_val_t{align});
251# else
252 operator delete(ptr, std::align_val_t{align});
253# endif
254}
255
262template <size_t Align, enable_if_t<Align <= MEMORY_ALIGN_THRESHHOLD, int> = 0>
263NEFORCE_CONSTEXPR20 void __deallocate_dispatch(void*& ptr, inner::alloc_size_t& bytes) noexcept {
264 inner::__deallocate_aux<Align>(ptr, bytes);
265}
266
267#endif // NEFORCE_STANDARD_17
268
269NEFORCE_END_INNER__
271
280template <size_t Align>
281NEFORCE_CONSTEXPR20 void deallocate(void* ptr, inner::alloc_size_t bytes) noexcept {
282#ifdef NEFORCE_STANDARD_20
283 if (_NEFORCE is_constant_evaluated()) {
284 operator delete(ptr);
285 return;
286 }
287#endif // NEFORCE_STANDARD_20
288
289#ifdef NEFORCE_STANDARD_17
290 inner::__deallocate_dispatch<Align>(ptr, bytes);
291#else
292 inner::__deallocate_aux<Align>(ptr, bytes);
293#endif // NEFORCE_STANDARD_17
294}
295
296
304template <typename T>
306 static_assert(is_allocable_v<T>, "allocator can`t alloc void, reference, function or const type.");
307
308public:
309 using value_type = T;
310 using pointer = T*;
311 using size_type = inner::alloc_size_t;
312
320 template <typename U>
321 struct rebind {
322 using other = standard_allocator<U>;
323 };
324
325private:
327 static constexpr inner::alloc_size_t align_size = alignof(T) > MEMORY_ALIGN_THRESHHOLD ? alignof(T)
328 : MEMORY_ALIGN_THRESHHOLD;
329
330public:
331 NEFORCE_CONSTEXPR20 standard_allocator() noexcept = default;
332
337 template <typename U>
338 NEFORCE_CONSTEXPR20 standard_allocator(const standard_allocator<U>& /*unused*/) noexcept {}
339
340 NEFORCE_CONSTEXPR20 ~standard_allocator() noexcept = default;
341
342 NEFORCE_CONSTEXPR20 standard_allocator& operator=(const standard_allocator&) noexcept = default;
343
352 NEFORCE_ALLOC_NODISCARD NEFORCE_CONSTEXPR20 NEFORCE_ALLOC_OPTIMIZE static pointer allocate(const size_type n) {
353 const size_type alloc_size = sizeof(value_type) * n;
354 NEFORCE_DEBUG_VERIFY(alloc_size <= static_cast<size_type>(-1), "allocation will cause memory overflow.");
355 try {
356 return static_cast<T*>(_NEFORCE allocate<align_size>(alloc_size));
357 } catch (...) {
358 NEFORCE_THROW_EXCEPTION(allocate_exception("standard allocate failed"));
359 }
360 unreachable();
361 }
362
368 NEFORCE_ALLOC_NODISCARD NEFORCE_CONSTEXPR20 NEFORCE_ALLOC_OPTIMIZE static pointer allocate() {
370 }
371
378 NEFORCE_CONSTEXPR20 static void deallocate(pointer p, const size_type n) noexcept {
379 NEFORCE_DEBUG_VERIFY(p != nullptr || n == 0, "null pointer cannot point to a block of non-zero size");
380 _NEFORCE deallocate<align_size>(p, n * sizeof(value_type));
381 }
382
387 NEFORCE_CONSTEXPR20 static void deallocate(pointer p) noexcept { standard_allocator::deallocate(p, 1); }
388
393 NEFORCE_NODISCARD static constexpr size_type max_size() noexcept {
394 return static_cast<size_type>(-1) / sizeof(value_type);
395 }
396};
397
404template <typename T, typename U>
405NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator==(const standard_allocator<T>& /*unused*/,
406 const standard_allocator<U>& /*unused*/) noexcept {
407 return true;
408}
409
416template <typename T, typename U>
417NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator!=(const standard_allocator<T>& /*unused*/,
418 const standard_allocator<U>& /*unused*/) noexcept {
419 return false;
420}
421
422
430template <typename T>
432 // MemoryAllocator
434
435NEFORCE_END_NAMESPACE__
436#endif // NEFORCE_CORE_MEMORY_STANDARD_ALLOCATOR_HPP__
constexpr standard_allocator() noexcept=default
默认构造函数
static constexpr void deallocate(pointer p, const size_type n) noexcept
释放先前分配的内存
static constexpr pointer allocate(const size_type n)
inner::alloc_size_t size_type
大小类型
constexpr ~standard_allocator() noexcept=default
析构函数
static constexpr void deallocate(pointer p) noexcept
释放单个元素内存
static constexpr size_type max_size() noexcept
获取分配器可分配的最大元素数量
static constexpr pointer allocate()
分配单个元素内存
调试断点和断言工具
异常处理框架
constexpr bool is_allocable_v
is_allocable的便捷变量模板
unsigned int uint32_t
32位无符号整数类型
void unreachable() noexcept
标记不可达代码路径
constexpr bool is_constant_evaluated() noexcept
检查当前上下文是否在常量求值中
bool operator!=(const function< Res(Args...)> &f, nullptr_t np) noexcept
不等于空指针比较
bool operator==(const function< Res(Args...)> &f, nullptr_t np) noexcept
等于空指针比较
constexpr void * allocate(const inner::alloc_size_t bytes)
内存分配函数
constexpr void deallocate(void *ptr, inner::alloc_size_t bytes) noexcept
内存释放函数
standard_allocator< T > allocator
标准分配器别名
uint64_t size_t
无符号大小类型
uint64_t uintptr_t
可容纳指针的无符号整数类型