1#ifndef NEFORCE_CORE_MEMORY_STANDARD_ALLOCATOR_HPP__
2#define NEFORCE_CORE_MEMORY_STANDARD_ALLOCATOR_HPP__
15NEFORCE_BEGIN_NAMESPACE__
27struct allocate_exception final : memory_exception {
28 explicit allocate_exception(
const char* info =
"Memory Allocation Failed.",
const char*
type = static_type) noexcept
30 memory_exception(info,
type) {}
32 explicit allocate_exception(
const exception& e) :
33 memory_exception(e) {}
35 ~allocate_exception()
override =
default;
36 static constexpr auto static_type =
"allocate_exception";
54NEFORCE_INLINE17
constexpr size_t MEMORY_ALIGN_THRESHHOLD = 16;
62NEFORCE_INLINE17
constexpr size_t MEMORY_BIG_ALLOC_THRESHHOLD = 4096;
73#ifdef NEFORCE_COMPILER_GCC
81#ifdef NEFORCE_COMPILER_MSVC
89NEFORCE_INLINE17
constexpr size_t MEMORY_BIG_ALLOC_ALIGN = 32;
97NEFORCE_INLINE17
constexpr size_t MEMORY_NO_USER_SIZE =
sizeof(
void*) + MEMORY_BIG_ALLOC_ALIGN -
99# ifdef NEFORCE_STATE_DEBUG
110NEFORCE_INLINE17
constexpr size_t MEMORY_BIG_ALLOC_SENTINEL =
111# ifdef NEFORCE_ARCH_BITS_64
112 0xFAFAFAFAFAFAFAFAUL;
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) {
136 const auto holder =
reinterpret_cast<uintptr_t>(
operator new(block_size));
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;
146 return operator new(bytes);
149#ifdef NEFORCE_STANDARD_17
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;
167# if defined(NEFORCE_COMPILER_CLANG) && defined(NEFORCE_STANDARD_20)
169 return operator new(bytes);
172 return operator new(bytes, std::align_val_t{align});
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);
201template <
size_t Align>
202NEFORCE_ALLOC_OPTIMIZE NEFORCE_CONSTEXPR20
void*
allocate(
const inner::alloc_size_t bytes) {
206#ifdef NEFORCE_STANDARD_20
208 return operator new(bytes);
212#ifdef NEFORCE_STANDARD_17
213 return inner::__allocate_dispatch<Align>(bytes);
215 return inner::__allocate_aux<Align>(bytes);
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;
239# ifdef NEFORCE_STATE_DEBUG
240 constexpr uintptr_t min_shift = 2 *
sizeof(
void*);
242 constexpr uintptr_t min_shift =
sizeof(
void*);
246 ptr =
reinterpret_cast<void*
>(holder);
249#if defined(NEFORCE_STANDARD_14) && defined(NEFORCE_COMPILER_MSVC)
250 operator delete(ptr, bytes);
252 operator delete(ptr);
256#ifdef NEFORCE_STANDARD_17
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;
274# if defined(NEFORCE_STANDARD_14) && defined(NEFORCE_COMPILER_MSVC)
275 operator delete(ptr, bytes, std::align_val_t{align});
277 operator delete(ptr, std::align_val_t{align});
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);
305template <
size_t Align>
306NEFORCE_CONSTEXPR20
void deallocate(
void* ptr, inner::alloc_size_t bytes)
noexcept {
307#ifdef NEFORCE_STANDARD_20
309 operator delete(ptr);
314#ifdef NEFORCE_STANDARD_17
315 inner::__deallocate_dispatch<Align>(ptr, bytes);
317 inner::__deallocate_aux<Align>(ptr, bytes);
331 static_assert(
is_allocable_v<T>,
"allocator can`t alloc void, reference, function or const type.");
345 template <
typename U>
352 static constexpr inner::alloc_size_t align_size =
alignof(T) > MEMORY_ALIGN_THRESHHOLD ?
alignof(T)
353 : MEMORY_ALIGN_THRESHHOLD;
362 template <typename U>
393 NEFORCE_ALLOC_NODISCARD NEFORCE_CONSTEXPR20 NEFORCE_ALLOC_OPTIMIZE
static pointer allocate() {
404 NEFORCE_DEBUG_VERIFY(p !=
nullptr || n == 0,
"null pointer cannot point to a block of non-zero size");
421template <
typename T,
typename U>
433template <
typename T,
typename U>
452NEFORCE_END_NAMESPACE__
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)
内存分配函数
exception(const char *info=static_type, const char *type=static_type, const int code=0)
构造函数
NEFORCE_NODISCARD const char * type() const noexcept
获取异常类型