32 #ifndef MCKL_CORE_MEMORY_HPP 33 #define MCKL_CORE_MEMORY_HPP 49 #include <jemalloc/jemalloc.h> 53 #include <tbb/scalable_allocator.h> 58 #ifndef MCKL_MEMORY_TYPE 59 #if MCKL_USE_TBB_MALLOC 60 #define MCKL_MEMORY_TYPE ::mckl::MemoryTBB 61 #elif MCKL_USE_JEMALLOC 62 #define MCKL_MEMORY_TYPE ::mckl::MemoryJEM 64 #define MCKL_MEMORY_TYPE ::mckl::MemorySYS 66 #define MCKL_MEMORY_TYPE ::mckl::MemorySTD 74 template <std::
size_t Alignment,
typename UIntType>
77 static_assert(Alignment != 0 && (Alignment & (Alignment - 1)) == 0,
78 "**alignment_round0** used with Alignment other than a power of two " 81 static_assert(Alignment >=
sizeof(
void *),
82 "**alignment_round0** used with Alignment less than sizeof(void *)");
84 static_assert(std::is_unsigned<UIntType>::value,
85 "alignment_round0** used with UIntType other than unsigned integer " 88 constexpr std::size_t addn = Alignment - 1;
89 constexpr std::size_t mask = ~addn;
91 return (n + addn) & mask;
94 template <std::
size_t Alignment,
typename UIntType>
97 return n == 0 ? Alignment : alignment_round0<Alignment>(n);
100 template <
typename T>
104 static constexpr std::size_t
value = std::is_scalar<T>::value ?
110 template <
typename T>
128 template <
typename T>
135 template <std::
size_t Alignment>
138 static_assert(Alignment != 0 && (Alignment & (Alignment - 1)) == 0,
139 "**MemorySTD** used with Alignment other than a power of two positive " 142 static_assert(Alignment >=
sizeof(
void *),
143 "**MemorySTD** used with Alignment less than sizeof(void *)");
146 static constexpr std::size_t
alignment() {
return Alignment; }
148 static void *
allocate(std::size_t n,
const void * =
nullptr) noexcept
150 const std::size_t m = internal::alignment_round0<Alignment>(
151 n +
sizeof(std::uintptr_t) + Alignment);
156 std::uintptr_t *
const address =
157 static_cast<std::uintptr_t *
>(std::malloc(m));
158 if (address ==
nullptr) {
162 std::uintptr_t *
const ptr =
reinterpret_cast<std::uintptr_t *
>(
163 internal::alignment_round0<Alignment>(
164 reinterpret_cast<std::uintptr_t
>(address + 1)));
165 ptr[-1] =
reinterpret_cast<std::uintptr_t
>(address);
167 return static_cast<void *
>(ptr);
172 if (ptr !=
nullptr) {
173 const std::uintptr_t address =
174 static_cast<std::uintptr_t *
>(ptr)[-1];
175 std::free(reinterpret_cast<void *>(address));
186 template <std::
size_t Alignment>
189 static_assert(Alignment != 0 && (Alignment & (Alignment - 1)) == 0,
190 "**MemorySYS** used with Alignment other than a power of two positive " 193 static_assert(Alignment >=
sizeof(
void *),
194 "**MemorySYS** used with Alignment less than sizeof(void *)");
197 static constexpr std::size_t
alignment() {
return Alignment; }
199 static void *
allocate(std::size_t n,
const void * =
nullptr) noexcept
201 const std::size_t m = internal::alignment_round<Alignment>(n);
208 if (::posix_memalign(&ptr, Alignment, m) != 0) {
217 if (ptr !=
nullptr) {
223 #endif // MCKL_HAS_POSIX 225 #if MCKL_HAS_JEMALLOC 231 template <std::
size_t Alignment>
234 static_assert(Alignment != 0 && (Alignment & (Alignment - 1)) == 0,
235 "**MemoryJEM** used with Alignment other than a power of two positive " 238 static_assert(Alignment >=
sizeof(
void *),
239 "**MemoryJEM** used with Alignment less than sizeof(void *)");
242 static constexpr std::size_t
alignment() {
return Alignment; }
244 static void *
allocate(std::size_t n,
const void * =
nullptr) noexcept
246 const std::size_t m = internal::alignment_round<Alignment>(n);
248 return m < n ? nullptr : ::aligned_alloc(Alignment, m);
253 if (ptr !=
nullptr) {
259 #endif // MCKL_HAS_JEMALLOC 267 template <std::
size_t Alignment>
270 static_assert(Alignment != 0 && (Alignment & (Alignment - 1)) == 0,
271 "**MemoryTBB** used with Alignment other than a power of two positive " 274 static_assert(Alignment >=
sizeof(
void *),
275 "**MemoryTBB** used with Alignment less than sizeof(void *)");
278 static constexpr std::size_t
alignment() {
return Alignment; }
280 static void *
allocate(std::size_t n,
const void * =
nullptr) noexcept
282 const std::size_t m = internal::alignment_round<Alignment>(n);
284 return m < n ? nullptr : scalable_aligned_malloc(m, Alignment);
289 if (ptr !=
nullptr) {
290 scalable_aligned_free(ptr);
295 #endif // MCKL_HAS_TBB 309 template <std::
size_t Alignment>
310 using Memory = MCKL_MEMORY_TYPE<Alignment>;
321 template <
typename T,
typename Mem = Memory<AlignOf<T>>>
325 template <
typename U>
334 template <
typename U>
336 : std::allocator<T>(
static_cast<std::allocator<U>
>(other))
340 T *
allocate(std::size_t n,
const void *hint =
nullptr)
342 const std::size_t m = n *
sizeof(T);
344 throw std::bad_alloc();
347 T *ptr =
static_cast<T *
>(Mem::allocate(m, hint));
348 if (ptr ==
nullptr) {
349 throw std::bad_alloc();
356 noexcept(Mem::deallocate(ptr, size)))
358 Mem::deallocate(ptr, size);
361 template <
typename U>
364 construct_dispatch(p, std::is_scalar<U>());
368 template <
typename U>
369 void construct_dispatch(U *, std::true_type)
373 template <
typename U>
374 void construct_dispatch(U *p, std::false_type)
376 ::new (static_cast<void *>(p)) U();
380 template <
typename Mem>
390 template <
typename U>
398 template <
typename Mem>
408 template <
typename U>
417 template <
typename T1,
typename T2,
typename Mem1,
typename Mem2>
421 return std::is_same<Mem1, Mem2>::value;
425 template <
typename T1,
typename T2,
typename Mem1,
typename Mem2>
429 return !std::is_same<Mem1, Mem2>::value;
434 template <
typename T,
typename Alloc = Allocator<T>>
439 #endif // MCKL_CORE_MEMORY_HPP Allocator(const Allocator< U, Mem > &other) noexcept
static void deallocate(void *ptr, std::size_t=0) noexcept
const void * const_pointer
std::vector< T, Alloc > Vector
std::vector with Allocator as the default allocator
std::true_type is_always_equal
T * allocate(std::size_t n, const void *hint=nullptr)
static void * allocate(std::size_t n, const void *=nullptr) noexcept
static constexpr std::size_t alignment()
static void deallocate(void *ptr, std::size_t=0) noexcept
static constexpr std::size_t value
constexpr bool operator==(const Allocator< T1, Mem1 > &, const Allocator< T2, Mem2 > &)
static void deallocate(void *ptr, std::size_t=0) noexcept
void deallocate(T *ptr, std::size_t size=0) noexcept(noexcept(Mem::deallocate(ptr, size)))
constexpr std::size_t alignment_round(UIntType n)
constexpr std::size_t AlignOf
Alignment of types in bytes.
static constexpr std::size_t alignment()
#define MCKL_MINIMUM_ALIGNMENT
The minimum alignment for any type.
constexpr std::size_t alignment_round0(UIntType n)
Memory allocation using the standard library.
std::true_type is_always_equal
Memory allocation using native system functions.
std::true_type propagate_on_container_move_assignment
std::true_type propagate_on_container_move_assignment
const void * const_pointer
#define MCKL_ALIGNMENT
The default alignment for scalar type.
Standard library compatible allocator with policies.
Memory allocation using jemalloc.
Memory allocation using Intel TBB.
static void * allocate(std::size_t n, const void *=nullptr) noexcept
static void * allocate(std::size_t n, const void *=nullptr) noexcept
static void * allocate(std::size_t n, const void *=nullptr) noexcept
static constexpr std::size_t alignment()
static void deallocate(void *ptr, std::size_t=0) noexcept
static constexpr std::size_t alignment()
constexpr bool operator!=(const Allocator< T1, Mem1 > &, const Allocator< T2, Mem2 > &)