KTL
aligned_malloc.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <cstddef>
4 #include <memory>
5 
6 // KTL_MALLOC_ALREADY_ALIGNED
7 #if defined(__GLIBC__) && ((__GLIBC__ >= 2 && __GLIBC_MINOR__ >= 8) || __GLIBC__ > 2) && defined(__LP64__)
8 #define KTL_GLIBC_MALLOC_ALREADY_ALIGNED 1
9 #else
10 #define KTL_GLIBC_MALLOC_ALREADY_ALIGNED 0
11 #endif
12 
13 #if defined(__FreeBSD__) && !defined(__arm__) && !defined(__mips__)
14 #define KTL_FREEBSD_MALLOC_ALREADY_ALIGNED 1
15 #else
16 #define KTL_FREEBSD_MALLOC_ALREADY_ALIGNED 0
17 #endif
18 
19 #if (defined(__APPLE__) \
20  || defined(_WIN64) \
21  || KTL_GLIBC_MALLOC_ALREADY_ALIGNED \
22  || KTL_FREEBSD_MALLOC_ALREADY_ALIGNED)
23 #define KTL_HAS_MALLOC_ALIGNED 1
24 #else
25 #define KTL_HAS_MALLOC_ALIGNED 0
26 #endif
27 // KTL_MALLOC_ALREADY_ALIGNED
28 
29 // KTL_HAS_POSIX_MEMALIGN
30 #if ((defined __QNXNTO__) || (defined _GNU_SOURCE) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))) \
31  && (defined _POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO > 0)
32 #define KTL_HAS_POSIX_MEMALIGN 1
33 #else
34 #define KTL_HAS_POSIX_MEMALIGN 0
35 #endif
36 // KTL_HAS_POSIX_MEMALIGN
37 
38 // KTL_HAS_MM_MALLOC
39 #if SSE_INSTR_SET > 0
40 #define KTL_HAS_MM_MALLOC 1
41 #else
42 #define KTL_HAS_MM_MALLOC 0
43 #endif
44 // KTL_HAS_MM_MALLOC
45 
46 namespace ktl::detail
47 {
48  inline void* aligned_malloc(size_t size, size_t alignment) noexcept
49  {
50 #if KTL_HAS_MALLOC_ALIGNED
51  return malloc(size);
52 #elif KTL_HAS_MM_MALLOC
53  return _mm_malloc(size, alignment);
54 #elif KTL_HAS_POSIX_MEMALIGN
55  void* res;
56  const int failed = posix_memalign(&res, size, alignment);
57  if (failed) res = nullptr;
58  return res;
59 #elif defined(_MSC_VER)
60  return _aligned_malloc(size, alignment);
61 #else
62  void* res = nullptr;
63  void* ptr = malloc(size + alignment);
64  if (ptr != nullptr)
65  {
66  res = reinterpret_cast<void*>((reinterpret_cast<size_t>(ptr) & ~(size_t(alignment - 1))) + alignment);
67  *(reinterpret_cast<void**>(res) - 1) = ptr;
68  }
69  return res;
70 #endif
71  }
72 
73  inline void aligned_free(void* ptr) noexcept
74  {
75 #if KTL_HAS_MALLOC_ALIGNED
76  free(ptr);
77 #elif KTL_HAS_MM_MALLOC
78  _mm_free(ptr);
79 #elif KTL_HAS_POSIX_MEMALIGN
80  free(ptr);
81 #elif defined(_MSC_VER)
82  _aligned_free(ptr);
83 #else
84  if (ptr != 0)
85  free(*(reinterpret_cast<void**>(ptr) - 1));
86 #endif
87  }
88 
89  template<typename T, typename... Args>
90  T* aligned_new(size_t alignment, Args&&... args)
91  noexcept(noexcept(T(std::declval<Args>()...)))
92  {
93  T* p = static_cast<T*>(aligned_malloc(sizeof(T), alignment));
94  ::new(p) T(std::forward<Args>(args)...);
95  return p;
96  }
97 
98  template<typename T>
99  void aligned_delete(T* p)
100  noexcept(noexcept(p->~T()))
101  {
102  p->~T();
103  aligned_free(p);
104  }
105 }
Definition: fallback_fwd.h:23
void * aligned_malloc(size_t size, size_t alignment) noexcept
Definition: aligned_malloc.h:48
void aligned_delete(T *p) noexcept(noexcept(p->~T()))
Definition: aligned_malloc.h:99
void aligned_free(void *ptr) noexcept
Definition: aligned_malloc.h:73
T * aligned_new(size_t alignment, Args &&... args) noexcept(noexcept(T(std::declval< Args >()...)))
Definition: aligned_malloc.h:90