9 /* Minimum alignment required by posix_memalign. */
10 #define DEF_ALIGN sizeof(void*)
12 void *al_malloc(size_t alignment
, size_t size
);
13 void *al_calloc(size_t alignment
, size_t size
);
14 void al_free(void *ptr
) noexcept
;
16 size_t al_get_page_size(void) noexcept
;
19 * Returns non-0 if the allocation function has direct alignment handling.
20 * Otherwise, the standard malloc is used with an over-allocation and pointer
23 int al_is_sane_alignment_allocator(void) noexcept
;
25 #define DEF_NEWDEL(T) \
26 void *operator new(size_t size) \
28 void *ret = al_malloc(alignof(T), size); \
29 if(!ret) throw std::bad_alloc(); \
32 void operator delete(void *block) noexcept { al_free(block); }
34 #define DEF_PLACE_NEWDEL() \
35 void *operator new(size_t /*size*/, void *ptr) noexcept { return ptr; } \
36 void operator delete(void *block) noexcept { al_free(block); }
40 template<typename T
, size_t alignment
=DEF_ALIGN
>
41 struct allocator
: public std::allocator
<T
> {
42 using size_type
= size_t;
44 using const_pointer
= const T
*;
48 using other
= allocator
<U
, alignment
>;
51 pointer
allocate(size_type n
, const void* = nullptr)
53 if(n
> std::numeric_limits
<size_t>::max() / sizeof(T
))
54 throw std::bad_alloc();
56 void *ret
{al_malloc(alignment
, n
*sizeof(T
))};
57 if(!ret
) throw std::bad_alloc();
58 return static_cast<pointer
>(ret
);
61 void deallocate(pointer p
, size_type
)
64 allocator() : std::allocator
<T
>() { }
65 allocator(const allocator
&a
) : std::allocator
<T
>(a
) { }
67 allocator(const allocator
<U
,alignment
> &a
) : std::allocator
<T
>(a
)
71 template<size_t alignment
, typename T
>
72 inline T
* assume_aligned(T
*ptr
) noexcept
74 static_assert((alignment
& (alignment
-1)) == 0, "alignment must be a power of 2");
76 return static_cast<T
*>(__builtin_assume_aligned(ptr
, alignment
));
77 #elif defined(_MSC_VER)
78 auto ptrval
= reinterpret_cast<uintptr_t>(ptr
);
79 if((ptrval
&(alignment
-1)) != 0) __assume(0);
80 return reinterpret_cast<T
*>(ptrval
);
86 /* std::make_unique was added with C++14, so until we rely on that, make our
89 template<typename T
, typename
...ArgsT
>
90 std::unique_ptr
<T
> make_unique(ArgsT
&&...args
)
91 { return std::unique_ptr
<T
>{new T
{std::forward
<ArgsT
>(args
)...}}; }
94 /* A flexible array type. Used either standalone or at the end of a parent
95 * struct, with placement new, to have a run-time-sized array that's embedded
98 template<typename T
,size_t alignment
=DEF_ALIGN
>
101 alignas(alignment
) T mArray
[];
103 static constexpr size_t CalcSizeof(size_t count
) noexcept
104 { return std::max
<size_t>(offsetof(FlexArray
, mArray
) + sizeof(T
)*count
, sizeof(FlexArray
)); }
106 FlexArray(size_t size
) : mSize
{size
}
107 { new (mArray
) T
[mSize
]; }
110 for(size_t i
{0u};i
< mSize
;++i
)
114 FlexArray(const FlexArray
&) = delete;
115 FlexArray
& operator=(const FlexArray
&) = delete;
117 size_t size() const noexcept
{ return mSize
; }
119 T
*data() noexcept
{ return mArray
; }
120 const T
*data() const noexcept
{ return mArray
; }
122 T
& operator[](size_t i
) noexcept
{ return mArray
[i
]; }
123 const T
& operator[](size_t i
) const noexcept
{ return mArray
[i
]; }
125 T
*begin() noexcept
{ return mArray
; }
126 const T
*begin() const noexcept
{ return mArray
; }
127 const T
*cbegin() const noexcept
{ return mArray
; }
128 T
*end() noexcept
{ return mArray
+ mSize
; }
129 const T
*end() const noexcept
{ return mArray
+ mSize
; }
130 const T
*cend() const noexcept
{ return mArray
+ mSize
; }
137 #endif /* AL_MALLOC_H */