MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
standard_allocator.hpp
浏览该文件的文档.
1#ifndef MSTL_CORE_MEMORY_STANDARD_ALLOCATOR_HPP__
2#define MSTL_CORE_MEMORY_STANDARD_ALLOCATOR_HPP__
3
11
13#include <new>
15
21
27MSTL_ERROR_BUILD_FINAL_CLASS(allocate_exception, memory_exception, "Memory Allocation Failed.")
28
29 // Exceptions
30
31
36
37
43MSTL_INLINE17 constexpr size_t MEMORY_ALIGN_THRESHHOLD = 16;
44
51MSTL_INLINE17 constexpr size_t MEMORY_BIG_ALLOC_THRESHHOLD = 4096;
52
55
60using alloc_size_t = size_t;
61
63// #ifdef MSTL_COMPILER_GCC__
64// using alloc_size_t = uint32_t;
65// #else
66// using alloc_size_t = size_t;
67// #endif
69
70
71#ifdef MSTL_COMPILER_MSVC__
72
79MSTL_INLINE17 constexpr size_t MEMORY_BIG_ALLOC_ALIGN = 32;
80
87MSTL_INLINE17 constexpr size_t MEMORY_NO_USER_SIZE =
88 sizeof(void*) + MEMORY_BIG_ALLOC_ALIGN - 1
89#ifdef MSTL_STATE_DEBUG__
90 * 2
91#endif
92;
93
100MSTL_INLINE17 constexpr size_t MEMORY_BIG_ALLOC_SENTINEL =
101#ifdef MSTL_DATA_BUS_WIDTH_64__
102 0xFAFAFAFAFAFAFAFAUL;
103#else
104 0xFAFAFAFAUL;
105#endif
106
107#endif // MSTL_COMPILER_MSVC__
108
109
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)); // align the memory address
129 static_cast<uintptr_t*>(ptr)[-1] = holder;
130#ifdef MSTL_STATE_DEBUG__
131 static_cast<uintptr_t*>(ptr)[-2] = MEMORY_BIG_ALLOC_SENTINEL;
132#endif
133 return ptr;
134 }
135#endif
136 return operator new(bytes);
137}
138
139#ifdef MSTL_STANDARD_17__
140
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;
155#endif
156#if defined(MSTL_COMPILER_CLANG__) && defined(MSTL_STANDARD_20__)
157 if (_MSTL is_constant_evaluated())
158 return operator new(bytes);
159#endif
160 return operator new(bytes, std::align_val_t{ align });
161}
162
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);
174}
175
176#endif
177
178MSTL_END_INNER__
180
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);
195#endif // MSTL_STANDARD_20__
196
197#ifdef MSTL_STANDARD_17__
198 return _INNER __allocate_dispatch<Align>(bytes);
199#else
200 return _INNER __allocate_aux<Align>(bytes);
201#endif // MSTL_STANDARD_17__
202}
203
204
207
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;
221 const uintptr_t* const user_ptr = static_cast<uintptr_t*>(ptr);
222 const uintptr_t holder = user_ptr[-1];
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*);
226#else
227 constexpr uintptr_t min_shift = sizeof(void*);
228#endif // MSTL_STATE_DEBUG__
229 const uintptr_t shift = reinterpret_cast<uintptr_t>(ptr) - holder;
230 MSTL_DEBUG_VERIFY(shift >= min_shift && shift <= MEMORY_NO_USER_SIZE, "invalid argument.");
231 ptr = reinterpret_cast<void*>(holder);
232 }
233#endif
234 operator delete(ptr
235#if defined(MSTL_STANDARD_14__) && defined(MSTL_COMPILER_MSVC__)
236 , bytes
237#endif
238 );
239}
240
241#ifdef MSTL_STANDARD_17__
242
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;
257 }
258#endif
259 operator delete(ptr,
260#if defined(MSTL_STANDARD_14__) && defined(MSTL_COMPILER_MSVC__)
261 bytes,
262#endif
263 std::align_val_t{ align });
264}
265
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);
275}
276
277#endif // MSTL_STANDARD_17__
278
279MSTL_END_INNER__
281
290template <size_t Align>
291MSTL_CONSTEXPR20 void deallocate(void* ptr, _INNER alloc_size_t bytes) noexcept {
292#ifdef MSTL_STANDARD_20__
293 if (_MSTL is_constant_evaluated()) {
294 operator delete(ptr);
295 return;
296 }
297#endif // MSTL_STANDARD_20__
298
299#ifdef MSTL_STANDARD_17__
300 _INNER __deallocate_dispatch<Align>(ptr, bytes);
301#else
302 _INNER __deallocate_aux<Align>(ptr, bytes);
303#endif // MSTL_STANDARD_17__
304}
305
306
314template <typename T>
316 static_assert(is_allocable_v<T>, "allocator can`t alloc void, reference, function or const type.");
317
318public:
319 using value_type = T;
320 using pointer = T*;
321 using size_type = _INNER alloc_size_t;
322
330 template <typename U>
331 struct rebind {
332 using other = standard_allocator<U>;
333 };
334
335private:
337 static constexpr _INNER alloc_size_t FINAL_ALIGN_SIZE =
338 alignof(T) > MEMORY_ALIGN_THRESHHOLD ? alignof(T) : MEMORY_ALIGN_THRESHHOLD;\
339
340 static constexpr size_type VALUE_SIZE = sizeof(value_type);
341
342public:
343 MSTL_CONSTEXPR20 standard_allocator() noexcept = default;
344
349 template <typename U>
350 MSTL_CONSTEXPR20 standard_allocator(const standard_allocator<U>&) noexcept {}
351
352 MSTL_CONSTEXPR20 ~standard_allocator() noexcept = default;
353
354 MSTL_CONSTEXPR20 standard_allocator& operator =(const standard_allocator&) noexcept = default;
355
364 MSTL_ALLOC_NODISCARD MSTL_CONSTEXPR20 MSTL_ALLOC_OPTIMIZE static pointer allocate(const size_type n) {
365 const size_type alloc_size = VALUE_SIZE * n;
366 MSTL_DEBUG_VERIFY(
367 alloc_size <= static_cast<size_type>(-1),
368 "allocation will cause memory overflow.");
369 try {
370 return static_cast<T*>(_MSTL allocate<FINAL_ALIGN_SIZE>(alloc_size));
371 } catch (...) {
372 throw_exception(allocate_exception("standard allocate failed"));
373 }
374 MSTL_UNREACHABLE;
375 }
376
382 MSTL_ALLOC_NODISCARD MSTL_CONSTEXPR20 MSTL_ALLOC_OPTIMIZE static pointer allocate() {
384 }
385
392 MSTL_CONSTEXPR20 static void deallocate(pointer p, const size_type n) noexcept {
393 MSTL_DEBUG_VERIFY(p != nullptr || n == 0, "null pointer cannot point to a block of non-zero size");
394 _MSTL deallocate<FINAL_ALIGN_SIZE>(p, n * VALUE_SIZE);
395 }
396
401 MSTL_CONSTEXPR20 static void deallocate(pointer p) noexcept {
403 }
404};
405
412template <typename T, typename U>
413MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator ==(
414 const standard_allocator<T>&, const standard_allocator<U>&) noexcept {
415 return true;
416}
417
424template <typename T, typename U>
425MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator !=(
426 const standard_allocator<T>&, const standard_allocator<U>&) noexcept {
427 return false;
428}
429
430
438template <typename T>
440 // MemoryAllocator
442
444#endif // MSTL_CORE_MEMORY_STANDARD_ALLOCATOR_HPP__
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
释放单个元素内存
MSTL异常处理框架
#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命名空间
uint64_t uintptr_t
可容纳指针的无符号整数类型
内存分配异常