10 #include <type_traits>
13 #include "pragmadefs.h"
16 [[gnu::alloc_align(1), gnu::alloc_size(2)]] void *al_malloc(size_t alignment
, size_t size
);
17 [[gnu::alloc_align(1), gnu::alloc_size(2)]] void *al_calloc(size_t alignment
, size_t size
);
18 void al_free(void *ptr
) noexcept
;
21 #define DISABLE_ALLOC() \
22 void *operator new(size_t) = delete; \
23 void *operator new[](size_t) = delete; \
24 void operator delete(void*) noexcept = delete; \
25 void operator delete[](void*) noexcept = delete;
27 #define DEF_NEWDEL(T) \
28 void *operator new(size_t size) \
30 void *ret = al_malloc(alignof(T), size); \
31 if(!ret) throw std::bad_alloc(); \
34 void *operator new[](size_t size) { return operator new(size); } \
35 void operator delete(void *block) noexcept { al_free(block); } \
36 void operator delete[](void *block) noexcept { operator delete(block); }
38 #define DEF_PLACE_NEWDEL() \
39 void *operator new(size_t /*size*/, void *ptr) noexcept { return ptr; } \
40 void *operator new[](size_t /*size*/, void *ptr) noexcept { return ptr; } \
41 void operator delete(void *block, void*) noexcept { al_free(block); } \
42 void operator delete(void *block) noexcept { al_free(block); } \
43 void operator delete[](void *block, void*) noexcept { al_free(block); } \
44 void operator delete[](void *block) noexcept { al_free(block); }
46 enum FamCount
: size_t { };
48 #define DEF_FAM_NEWDEL(T, FamMem) \
49 static constexpr size_t Sizeof(size_t count) noexcept \
51 return std::max<size_t>(sizeof(T), \
52 decltype(FamMem)::Sizeof(count, offsetof(T, FamMem))); \
55 void *operator new(size_t /*size*/, FamCount count) \
57 if(void *ret{al_malloc(alignof(T), T::Sizeof(count))}) \
59 throw std::bad_alloc(); \
61 void *operator new[](size_t /*size*/) = delete; \
62 void operator delete(void *block, FamCount) { al_free(block); } \
63 void operator delete(void *block) noexcept { al_free(block); } \
64 void operator delete[](void* /*block*/) = delete;
69 #define REQUIRES(...) typename std::enable_if<(__VA_ARGS__),int>::type = 0
71 template<typename T
, std::size_t alignment
=alignof(T
)>
75 using const_reference
= const T
&;
77 using const_pointer
= const T
*;
78 using size_type
= std::size_t;
79 using difference_type
= std::ptrdiff_t;
80 using is_always_equal
= std::true_type
;
84 using other
= allocator
<U
, (alignment
<alignof(U
))?alignof(U
):alignment
>;
87 allocator() noexcept
= default;
88 template<typename U
, std::size_t N
>
89 constexpr allocator(const allocator
<U
,N
>&) noexcept
{ }
91 [[gnu::assume_aligned(alignment
), gnu::alloc_size(2)]] T
*allocate(std::size_t n
)
93 if(n
> std::numeric_limits
<std::size_t>::max()/sizeof(T
)) throw std::bad_alloc();
94 if(auto p
= static_cast<T
*>(al_malloc(alignment
, n
*sizeof(T
)))) return p
;
95 throw std::bad_alloc();
97 void deallocate(T
*p
, std::size_t) noexcept
{ al_free(p
); }
99 template<typename T
, std::size_t N
, typename U
, std::size_t M
>
100 bool operator==(const allocator
<T
,N
>&, const allocator
<U
,M
>&) noexcept
{ return true; }
101 template<typename T
, std::size_t N
, typename U
, std::size_t M
>
102 bool operator!=(const allocator
<T
,N
>&, const allocator
<U
,M
>&) noexcept
{ return false; }
104 template<size_t alignment
, typename T
>
105 [[gnu::assume_aligned(alignment
)]] inline T
* assume_aligned(T
*ptr
) noexcept
{ return ptr
; }
107 /* At least VS 2015 complains that 'ptr' is unused when the given type's
108 * destructor is trivial (a no-op). So disable that warning for this call.
111 msc_pragma(warning(disable
: 4100))
113 inline void destroy_at(T
*ptr
) { ptr
->~T(); }
117 inline void destroy(T first
, const T end
)
121 al::destroy_at(std::addressof(*first
));
126 template<typename T
, typename N
, REQUIRES(std::is_integral
<N
>::value
)>
127 inline T
destroy_n(T first
, N count
)
132 al::destroy_at(std::addressof(*first
));
140 template<typename T
, typename N
, REQUIRES(std::is_integral
<N
>::value
)>
141 inline T
uninitialized_default_construct_n(T first
, N count
)
143 using ValueT
= typename
std::iterator_traits
<T
>::value_type
;
149 ::new(static_cast<void*>(std::addressof(*current
))) ValueT
;
154 al::destroy(first
, current
);
162 /* A flexible array type. Used either standalone or at the end of a parent
163 * struct, with placement new, to have a run-time-sized array that's embedded
166 template<typename T
, size_t alignment
=alignof(T
)>
168 using element_type
= T
;
169 using value_type
= std::remove_cv_t
<T
>;
170 using index_type
= size_t;
171 using difference_type
= ptrdiff_t;
174 using const_pointer
= const T
*;
175 using reference
= T
&;
176 using const_reference
= const T
&;
178 using iterator
= pointer
;
179 using const_iterator
= const_pointer
;
180 using reverse_iterator
= std::reverse_iterator
<iterator
>;
181 using const_reverse_iterator
= std::reverse_iterator
<const_iterator
>;
184 const index_type mSize
;
187 alignas(alignment
) element_type mArray
[1];
190 static std::unique_ptr
<FlexArray
> Create(index_type count
)
192 void *ptr
{al_calloc(alignof(FlexArray
), Sizeof(count
))};
193 return std::unique_ptr
<FlexArray
>{new(ptr
) FlexArray
{count
}};
195 static constexpr index_type
Sizeof(index_type count
, index_type base
=0u) noexcept
198 std::max
<index_type
>(offsetof(FlexArray
, mArray
) + sizeof(T
)*count
, sizeof(FlexArray
));
201 FlexArray(index_type size
) : mSize
{size
}
202 { al::uninitialized_default_construct_n(mArray
, mSize
); }
203 ~FlexArray() { al::destroy_n(mArray
, mSize
); }
205 FlexArray(const FlexArray
&) = delete;
206 FlexArray
& operator=(const FlexArray
&) = delete;
208 index_type
size() const noexcept
{ return mSize
; }
209 bool empty() const noexcept
{ return mSize
== 0; }
211 pointer
data() noexcept
{ return mArray
; }
212 const_pointer
data() const noexcept
{ return mArray
; }
214 reference
operator[](index_type i
) noexcept
{ return mArray
[i
]; }
215 const_reference
operator[](index_type i
) const noexcept
{ return mArray
[i
]; }
217 reference
front() noexcept
{ return mArray
[0]; }
218 const_reference
front() const noexcept
{ return mArray
[0]; }
220 reference
back() noexcept
{ return mArray
[mSize
-1]; }
221 const_reference
back() const noexcept
{ return mArray
[mSize
-1]; }
223 iterator
begin() noexcept
{ return mArray
; }
224 const_iterator
begin() const noexcept
{ return mArray
; }
225 const_iterator
cbegin() const noexcept
{ return mArray
; }
226 iterator
end() noexcept
{ return mArray
+ mSize
; }
227 const_iterator
end() const noexcept
{ return mArray
+ mSize
; }
228 const_iterator
cend() const noexcept
{ return mArray
+ mSize
; }
230 reverse_iterator
rbegin() noexcept
{ return end(); }
231 const_reverse_iterator
rbegin() const noexcept
{ return end(); }
232 const_reverse_iterator
crbegin() const noexcept
{ return cend(); }
233 reverse_iterator
rend() noexcept
{ return begin(); }
234 const_reverse_iterator
rend() const noexcept
{ return begin(); }
235 const_reverse_iterator
crend() const noexcept
{ return cbegin(); }
244 #endif /* AL_MALLOC_H */