NexusForce 1.0.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
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
27struct allocate_exception final : memory_exception {
28 explicit allocate_exception(const char* info = "Memory Allocation Failed.", const char* type = static_type) noexcept
29 :
30 memory_exception(info, type) {}
31
32 explicit allocate_exception(const exception& e) :
33 memory_exception(e) {}
34
35 ~allocate_exception() override = default;
36 static constexpr auto static_type = "allocate_exception";
37};
38
39 // Exceptions
41
47
54NEFORCE_INLINE17 constexpr size_t MEMORY_ALIGN_THRESHHOLD = 16;
55
62NEFORCE_INLINE17 constexpr size_t MEMORY_BIG_ALLOC_THRESHHOLD = 4096;
63
65NEFORCE_BEGIN_INNER__
66
71using alloc_size_t =
73#ifdef NEFORCE_COMPILER_GCC
75#else
76 size_t;
77#endif
79
80
81#ifdef NEFORCE_COMPILER_MSVC
82
89NEFORCE_INLINE17 constexpr size_t MEMORY_BIG_ALLOC_ALIGN = 32;
90
97NEFORCE_INLINE17 constexpr size_t MEMORY_NO_USER_SIZE = sizeof(void*) + MEMORY_BIG_ALLOC_ALIGN -
98 1
99# ifdef NEFORCE_STATE_DEBUG
100 * 2
101# endif
102 ;
103
110NEFORCE_INLINE17 constexpr size_t MEMORY_BIG_ALLOC_SENTINEL =
111# ifdef NEFORCE_ARCH_BITS_64
112 0xFAFAFAFAFAFAFAFAUL;
113# else
114 0xFAFAFAFAUL;
115# endif
116
117#endif // NEFORCE_COMPILER_MSVC
118
119
128template <size_t Align>
129NEFORCE_ALLOC_OPTIMIZE NEFORCE_CONSTEXPR20 void* __allocate_aux(const alloc_size_t bytes) {
130#ifdef NEFORCE_COMPILER_MSVC
131 if (bytes >= MEMORY_BIG_ALLOC_THRESHHOLD) {
132 const size_t block_size = MEMORY_NO_USER_SIZE + bytes;
133 if (block_size <= bytes) {
134 NEFORCE_THROW_EXCEPTION(memory_exception("invalid block size."));
135 }
136 const auto holder = reinterpret_cast<uintptr_t>(operator new(block_size));
137 NEFORCE_DEBUG_VERIFY(holder != 0, "invalid argument");
138 const auto ptr = reinterpret_cast<void*>((holder + MEMORY_NO_USER_SIZE) & ~(MEMORY_BIG_ALLOC_ALIGN - 1));
139 static_cast<uintptr_t*>(ptr)[-1] = holder;
140# ifdef NEFORCE_STATE_DEBUG
141 static_cast<uintptr_t*>(ptr)[-2] = MEMORY_BIG_ALLOC_SENTINEL;
142# endif
143 return ptr;
144 }
145#endif
146 return operator new(bytes);
147}
148
149#ifdef NEFORCE_STANDARD_17
150
159template <size_t Align, enable_if_t<(Align > MEMORY_ALIGN_THRESHHOLD), int> = 0>
160NEFORCE_ALLOC_OPTIMIZE NEFORCE_CONSTEXPR20 void* __allocate_dispatch(const alloc_size_t bytes) {
161 size_t align = Align;
162# ifdef NEFORCE_COMPILER_MSVC
163 if (bytes >= MEMORY_BIG_ALLOC_THRESHHOLD) {
164 align = Align > MEMORY_BIG_ALLOC_ALIGN ? Align : MEMORY_BIG_ALLOC_ALIGN;
165 }
166# endif
167# if defined(NEFORCE_COMPILER_CLANG) && defined(NEFORCE_STANDARD_20)
168 if (_NEFORCE is_constant_evaluated()) {
169 return operator new(bytes);
170 }
171# endif
172 return operator new(bytes, std::align_val_t{align});
173}
174
183template <size_t Align, enable_if_t<Align <= MEMORY_ALIGN_THRESHHOLD, int> = 0>
184NEFORCE_ALLOC_OPTIMIZE NEFORCE_CONSTEXPR20 void* __allocate_dispatch(const alloc_size_t bytes) {
185 return inner::__allocate_aux<Align>(bytes);
186}
187
188#endif
189
190NEFORCE_END_INNER__
192
201template <size_t Align>
202NEFORCE_ALLOC_OPTIMIZE NEFORCE_CONSTEXPR20 void* allocate(const inner::alloc_size_t bytes) {
203 if (bytes == 0) {
204 return nullptr;
205 }
206#ifdef NEFORCE_STANDARD_20
207 if (_NEFORCE is_constant_evaluated()) {
208 return operator new(bytes);
209 }
210#endif // NEFORCE_STANDARD_20
211
212#ifdef NEFORCE_STANDARD_17
213 return inner::__allocate_dispatch<Align>(bytes);
214#else
215 return inner::__allocate_aux<Align>(bytes);
216#endif // NEFORCE_STANDARD_17
217}
218
219
221NEFORCE_BEGIN_INNER__
222
231template <size_t Align>
232void __deallocate_aux(void*& ptr, inner::alloc_size_t& bytes) noexcept {
233#ifdef NEFORCE_COMPILER_MSVC
234 if (bytes >= MEMORY_BIG_ALLOC_THRESHHOLD) {
235 bytes += MEMORY_NO_USER_SIZE;
236 const uintptr_t* const user_ptr = static_cast<uintptr_t*>(ptr);
237 const uintptr_t holder = user_ptr[-1];
238 NEFORCE_DEBUG_VERIFY(user_ptr[-2] == MEMORY_BIG_ALLOC_SENTINEL, "invalid sentinel.");
239# ifdef NEFORCE_STATE_DEBUG
240 constexpr uintptr_t min_shift = 2 * sizeof(void*);
241# else
242 constexpr uintptr_t min_shift = sizeof(void*);
243# endif
244 const uintptr_t shift = reinterpret_cast<uintptr_t>(ptr) - holder;
245 NEFORCE_DEBUG_VERIFY(shift >= min_shift && shift <= MEMORY_NO_USER_SIZE, "invalid argument.");
246 ptr = reinterpret_cast<void*>(holder);
247 }
248#endif
249#if defined(NEFORCE_STANDARD_14) && defined(NEFORCE_COMPILER_MSVC)
250 operator delete(ptr, bytes);
251#else
252 operator delete(ptr);
253#endif
254}
255
256#ifdef NEFORCE_STANDARD_17
257
266template <size_t Align, enable_if_t<(Align > MEMORY_ALIGN_THRESHHOLD), int> = 0>
267NEFORCE_CONSTEXPR20 void __deallocate_dispatch(void*& ptr, inner::alloc_size_t& bytes) noexcept {
268 size_t align = Align;
269# ifdef NEFORCE_COMPILER_MSVC
270 if (bytes > MEMORY_BIG_ALLOC_THRESHHOLD) {
271 align = Align > MEMORY_BIG_ALLOC_ALIGN ? Align : MEMORY_BIG_ALLOC_ALIGN;
272 }
273# endif
274# if defined(NEFORCE_STANDARD_14) && defined(NEFORCE_COMPILER_MSVC)
275 operator delete(ptr, bytes, std::align_val_t{align});
276# else
277 operator delete(ptr, std::align_val_t{align});
278# endif
279}
280
287template <size_t Align, enable_if_t<Align <= MEMORY_ALIGN_THRESHHOLD, int> = 0>
288NEFORCE_CONSTEXPR20 void __deallocate_dispatch(void*& ptr, inner::alloc_size_t& bytes) noexcept {
289 inner::__deallocate_aux<Align>(ptr, bytes);
290}
291
292#endif // NEFORCE_STANDARD_17
293
294NEFORCE_END_INNER__
296
305template <size_t Align>
306NEFORCE_CONSTEXPR20 void deallocate(void* ptr, inner::alloc_size_t bytes) noexcept {
307#ifdef NEFORCE_STANDARD_20
308 if (_NEFORCE is_constant_evaluated()) {
309 operator delete(ptr);
310 return;
311 }
312#endif // NEFORCE_STANDARD_20
313
314#ifdef NEFORCE_STANDARD_17
315 inner::__deallocate_dispatch<Align>(ptr, bytes);
316#else
317 inner::__deallocate_aux<Align>(ptr, bytes);
318#endif // NEFORCE_STANDARD_17
319}
320
321
329template <typename T>
331 static_assert(is_allocable_v<T>, "allocator can`t alloc void, reference, function or const type.");
332
333public:
334 using value_type = T;
335 using pointer = T*;
336 using size_type = inner::alloc_size_t;
337
345 template <typename U>
346 struct rebind {
347 using other = standard_allocator<U>;
348 };
349
350private:
352 static constexpr inner::alloc_size_t align_size = alignof(T) > MEMORY_ALIGN_THRESHHOLD ? alignof(T)
353 : MEMORY_ALIGN_THRESHHOLD;
354
355public:
356 NEFORCE_CONSTEXPR20 standard_allocator() noexcept = default;
357
362 template <typename U>
363 NEFORCE_CONSTEXPR20 standard_allocator(const standard_allocator<U>&) noexcept {}
364
365 NEFORCE_CONSTEXPR20 ~standard_allocator() noexcept = default;
366
367 NEFORCE_CONSTEXPR20 standard_allocator& operator=(const standard_allocator&) noexcept = default;
368
377 NEFORCE_ALLOC_NODISCARD NEFORCE_CONSTEXPR20 NEFORCE_ALLOC_OPTIMIZE static pointer allocate(const size_type n) {
378 const size_type alloc_size = sizeof(value_type) * n;
379 NEFORCE_DEBUG_VERIFY(alloc_size <= static_cast<size_type>(-1), "allocation will cause memory overflow.");
380 try {
381 return static_cast<T*>(_NEFORCE allocate<align_size>(alloc_size));
382 } catch (...) {
383 NEFORCE_THROW_EXCEPTION(allocate_exception("standard allocate failed"));
384 }
385 unreachable();
386 }
387
393 NEFORCE_ALLOC_NODISCARD NEFORCE_CONSTEXPR20 NEFORCE_ALLOC_OPTIMIZE static pointer allocate() {
395 }
396
403 NEFORCE_CONSTEXPR20 static void deallocate(pointer p, const size_type n) noexcept {
404 NEFORCE_DEBUG_VERIFY(p != nullptr || n == 0, "null pointer cannot point to a block of non-zero size");
405 _NEFORCE deallocate<align_size>(p, n * sizeof(value_type));
406 }
407
412 NEFORCE_CONSTEXPR20 static void deallocate(pointer p) noexcept { standard_allocator::deallocate(p, 1); }
413};
414
421template <typename T, typename U>
422NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator==(const standard_allocator<T>&,
423 const standard_allocator<U>&) noexcept {
424 return true;
425}
426
433template <typename T, typename U>
434NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator!=(const standard_allocator<T>&,
435 const standard_allocator<U>&) noexcept {
436 return false;
437}
438
439
447template <typename T>
449 // MemoryAllocator
451
452NEFORCE_END_NAMESPACE__
453#endif // NEFORCE_CORE_MEMORY_STANDARD_ALLOCATOR_HPP__
调试断点和断言工具
static NEFORCE_CONSTEXPR20 void deallocate(pointer p) noexcept
释放单个元素内存
NEFORCE_ALLOC_NODISCARD NEFORCE_CONSTEXPR20 static NEFORCE_ALLOC_OPTIMIZE pointer allocate(const size_type n)
static NEFORCE_CONSTEXPR20 void deallocate(pointer p, const size_type n) noexcept
释放先前分配的内存
inner::alloc_size_t size_type
大小类型
NEFORCE_CONSTEXPR20 standard_allocator() noexcept=default
默认构造函数
NEFORCE_ALLOC_NODISCARD NEFORCE_CONSTEXPR20 static NEFORCE_ALLOC_OPTIMIZE pointer allocate()
分配单个元素内存
NEFORCE_CONSTEXPR20 ~standard_allocator() noexcept=default
析构函数
异常处理框架
NEFORCE_INLINE17 constexpr bool is_allocable_v
is_allocable的便捷变量模板
unsigned int uint32_t
32位无符号整数类型
#define NEFORCE_DEBUG_VERIFY(CON, MESG)
调试模式断言
NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE_INLINE constexpr bool is_constant_evaluated() noexcept
检查当前上下文是否在常量求值中
NEFORCE_NORETURN NEFORCE_ALWAYS_INLINE_INLINE void unreachable() noexcept
标记不可达代码路径
standard_allocator< T > allocator
标准分配器别名
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator!=(const standard_allocator< T > &, const standard_allocator< U > &) noexcept
比较两个分配器是否不等
NEFORCE_CONSTEXPR20 void deallocate(void *ptr, inner::alloc_size_t bytes) noexcept
内存释放函数
NEFORCE_NODISCARD NEFORCE_CONSTEXPR20 bool operator==(const standard_allocator< T > &, const standard_allocator< U > &) noexcept
比较两个分配器是否相等
NEFORCE_ALLOC_OPTIMIZE NEFORCE_CONSTEXPR20 void * allocate(const inner::alloc_size_t bytes)
内存分配函数
uint64_t size_t
无符号大小类型
uint64_t uintptr_t
可容纳指针的无符号整数类型
exception(const char *info=static_type, const char *type=static_type, const int code=0)
构造函数
NEFORCE_NODISCARD const char * type() const noexcept
获取异常类型
内存操作异常