1#ifndef MSTL_CORE_MEMORY_STANDARD_ALLOCATOR_HPP__
2#define MSTL_CORE_MEMORY_STANDARD_ALLOCATOR_HPP__
43MSTL_INLINE17 constexpr
size_t MEMORY_ALIGN_THRESHHOLD = 16;
51MSTL_INLINE17 constexpr
size_t MEMORY_BIG_ALLOC_THRESHHOLD = 4096;
60using alloc_size_t =
size_t;
71#ifdef MSTL_COMPILER_MSVC__
79MSTL_INLINE17
constexpr size_t MEMORY_BIG_ALLOC_ALIGN = 32;
87MSTL_INLINE17
constexpr size_t MEMORY_NO_USER_SIZE =
88 sizeof(
void*) + MEMORY_BIG_ALLOC_ALIGN - 1
89#ifdef MSTL_STATE_DEBUG__
100MSTL_INLINE17
constexpr size_t MEMORY_BIG_ALLOC_SENTINEL =
101#ifdef MSTL_DATA_BUS_WIDTH_64__
102 0xFAFAFAFAFAFAFAFAUL;
118template <
size_t Align>
119MSTL_ALLOC_OPTIMIZE MSTL_CONSTEXPR20
void* __allocate_aux(
const alloc_size_t bytes) {
120#ifdef MSTL_COMPILER_MSVC__
121 if (bytes >= MEMORY_BIG_ALLOC_THRESHHOLD) {
122 const size_t block_size = MEMORY_NO_USER_SIZE + bytes;
123 if (block_size <= bytes)
124 throw_exception(memory_exception(
"invalid block size."));
125 const auto holder =
reinterpret_cast<uintptr_t>(
operator new(block_size));
126 MSTL_DEBUG_VERIFY(holder != 0,
"invalid argument");
127 const auto ptr =
reinterpret_cast<void*
>(
128 (holder + MEMORY_NO_USER_SIZE) & ~(MEMORY_BIG_ALLOC_ALIGN - 1));
129 static_cast<uintptr_t*
>(ptr)[-1] = holder;
130#ifdef MSTL_STATE_DEBUG__
131 static_cast<uintptr_t*
>(ptr)[-2] = MEMORY_BIG_ALLOC_SENTINEL;
136 return operator new(bytes);
139#ifdef MSTL_STANDARD_17__
149template <
size_t Align, enable_if_t<(Align > MEMORY_ALIGN_THRESHHOLD) ,
int> = 0>
150MSTL_ALLOC_OPTIMIZE MSTL_CONSTEXPR20
void* __allocate_dispatch(
const alloc_size_t bytes) {
151 size_t align = Align;
152#ifdef MSTL_COMPILER_MSVC__
153 if (bytes >= MEMORY_BIG_ALLOC_THRESHHOLD)
154 align = Align > MEMORY_BIG_ALLOC_ALIGN ? Align : MEMORY_BIG_ALLOC_ALIGN;
156#if defined(MSTL_COMPILER_CLANG__) && defined(MSTL_STANDARD_20__)
157 if (
_MSTL is_constant_evaluated())
158 return operator new(bytes);
160 return operator new(bytes, std::align_val_t{ align });
171template <
size_t Align, enable_if_t<Align <= MEMORY_ALIGN_THRESHHOLD,
int> = 0>
172MSTL_ALLOC_OPTIMIZE MSTL_CONSTEXPR20
void* __allocate_dispatch(const alloc_
size_t bytes) {
173 return _INNER __allocate_aux<Align>(
bytes);
189template <
size_t Align>
190MSTL_ALLOC_OPTIMIZE MSTL_CONSTEXPR20
void*
allocate(
const _INNER alloc_size_t bytes) {
191 if (bytes == 0)
return nullptr;
192#ifdef MSTL_STANDARD_20__
193 if (
_MSTL is_constant_evaluated())
194 return operator new(bytes);
197#ifdef MSTL_STANDARD_17__
198 return _INNER __allocate_dispatch<Align>(bytes);
200 return _INNER __allocate_aux<Align>(bytes);
216template <
size_t Align>
217void __deallocate_aux(
void*& ptr,
_INNER alloc_size_t& bytes)
noexcept {
218#ifdef MSTL_COMPILER_MSVC__
219 if (bytes >= MEMORY_BIG_ALLOC_THRESHHOLD) {
220 bytes += MEMORY_NO_USER_SIZE;
223 MSTL_DEBUG_VERIFY(user_ptr[-2] == MEMORY_BIG_ALLOC_SENTINEL,
"invalid sentinel.");
224#ifdef MSTL_STATE_DEBUG__
225 constexpr uintptr_t min_shift = 2 *
sizeof(
void*);
227 constexpr uintptr_t min_shift =
sizeof(
void*);
230 MSTL_DEBUG_VERIFY(shift >= min_shift && shift <= MEMORY_NO_USER_SIZE,
"invalid argument.");
231 ptr =
reinterpret_cast<void*
>(holder);
235#if defined(MSTL_STANDARD_14__) && defined(MSTL_COMPILER_MSVC__)
241#ifdef MSTL_STANDARD_17__
251template <
size_t Align, enable_if_t<(Align > MEMORY_ALIGN_THRESHHOLD),
int> = 0>
252MSTL_CONSTEXPR20
void __deallocate_dispatch(
void*& ptr,
_INNER alloc_size_t& bytes)
noexcept {
253 size_t align = Align;
254#ifdef MSTL_COMPILER_MSVC__
255 if (bytes > MEMORY_BIG_ALLOC_THRESHHOLD) {
256 align = Align > MEMORY_BIG_ALLOC_ALIGN ? Align : MEMORY_BIG_ALLOC_ALIGN;
260#if defined(MSTL_STANDARD_14__) && defined(MSTL_COMPILER_MSVC__)
263 std::align_val_t{ align });
272template <
size_t Align, enable_if_t<Align <= MEMORY_ALIGN_THRESHHOLD,
int> = 0>
273MSTL_CONSTEXPR20
void __deallocate_dispatch(
void*& ptr, _INNER alloc_
size_t&
bytes) noexcept {
274 _INNER __deallocate_aux<Align>(ptr,
bytes);
290template <
size_t Align>
292#ifdef MSTL_STANDARD_20__
293 if (
_MSTL is_constant_evaluated()) {
294 operator delete(ptr);
299#ifdef MSTL_STANDARD_17__
300 _INNER __deallocate_dispatch<Align>(ptr, bytes);
302 _INNER __deallocate_aux<Align>(ptr, bytes);
316 static_assert(is_allocable_v<T>,
"allocator can`t alloc void, reference, function or const type.");
330 template <
typename U>
337 static constexpr _INNER alloc_size_t FINAL_ALIGN_SIZE =
338 alignof(T) > MEMORY_ALIGN_THRESHHOLD ?
alignof(T) : MEMORY_ALIGN_THRESHHOLD;\
349 template <typename U>
365 const size_type alloc_size = VALUE_SIZE * n;
367 alloc_size <=
static_cast<size_type>(-1),
368 "allocation will cause memory overflow.");
393 MSTL_DEBUG_VERIFY(p !=
nullptr || n == 0,
"null pointer cannot point to a block of non-zero size");
412template <
typename T,
typename U>
424template <
typename T,
typename U>
MSTL_ALLOC_NODISCARD MSTL_CONSTEXPR20 static MSTL_ALLOC_OPTIMIZE pointer allocate()
分配单个元素内存
_INNER alloc_size_t size_type
大小类型
MSTL_CONSTEXPR20 standard_allocator() noexcept=default
默认构造函数
static MSTL_CONSTEXPR20 void deallocate(pointer p, const size_type n) noexcept
释放先前分配的内存
MSTL_CONSTEXPR20 ~standard_allocator() noexcept=default
析构函数
MSTL_ALLOC_NODISCARD MSTL_CONSTEXPR20 static MSTL_ALLOC_OPTIMIZE pointer allocate(const size_type n)
static MSTL_CONSTEXPR20 void deallocate(pointer p) noexcept
释放单个元素内存
#define MSTL_ERROR_BUILD_FINAL_CLASS(THIS, BASE, INFO)
构建最终异常类宏
MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator==(const standard_allocator< T > &, const standard_allocator< U > &) noexcept
比较两个分配器是否相等
standard_allocator< T > allocator
标准分配器别名
MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator!=(const standard_allocator< T > &, const standard_allocator< U > &) noexcept
比较两个分配器是否不等
MSTL_ALLOC_OPTIMIZE MSTL_CONSTEXPR20 void * allocate(const _INNER alloc_size_t bytes)
内存分配函数
MSTL_CONSTEXPR20 void deallocate(void *ptr, _INNER alloc_size_t bytes) noexcept
内存释放函数
#define _MSTL
全局命名空间MSTL前缀
#define _INNER
inner命名空间前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
#define MSTL_BEGIN_INNER__
开始inner命名空间