xref: /aosp_15_r20/external/XNNPACK/src/xnnpack/aligned-allocator.h (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1 // Copyright (c) Facebook, Inc. and its affiliates.
2 // All rights reserved.
3 //
4 // This source code is licensed under the BSD-style license found in the
5 // LICENSE file in the root directory of this source tree.
6 
7 #pragma once
8 
9 #include <cstddef>
10 #include <limits>
11 #include <memory>
12 #include <type_traits>
13 #include <utility>
14 
15 #include <stdlib.h>
16 
17 #if defined(__ANDROID__) || defined(_WIN32) || defined(__CYGWIN__)
18   #include <malloc.h>
19 #endif
20 
21 
22 template <typename T, size_t Alignment>
23 class AlignedAllocator;
24 
25 template <size_t Alignment>
26 class AlignedAllocator<void, Alignment> {
27  public:
28   typedef void* pointer;
29   typedef const void* const_pointer;
30   typedef void value_type;
31 
32   template <class U>
33   struct rebind {
34     typedef AlignedAllocator<U, Alignment> other;
35   };
36 };
37 
38 template <typename T, size_t Alignment>
39 class AlignedAllocator {
40  public:
41   typedef T value_type;
42   typedef T* pointer;
43   typedef const T* const_pointer;
44   typedef T& reference;
45   typedef const T& const_reference;
46   typedef size_t size_type;
47   typedef ptrdiff_t difference_type;
48 
49 #if __cplusplus >= 201402L
50   typedef std::true_type propagate_on_container_move_assignment;
51 #endif
52 
53   template <class U>
54   struct rebind {
55     typedef AlignedAllocator<U, Alignment> other;
56   };
57 
58  public:
AlignedAllocator()59   inline AlignedAllocator() noexcept {}
60 
61   template <class U>
AlignedAllocator(const AlignedAllocator<U,Alignment> & other)62   inline AlignedAllocator(
63       const AlignedAllocator<U, Alignment>& other) noexcept {}
64 
max_size()65   inline size_type max_size() const noexcept {
66     return (std::numeric_limits<size_type>::max() - size_type(Alignment)) /
67         sizeof(T);
68   }
69 
address(reference x)70   inline pointer address(reference x) const noexcept {
71     return std::addressof(x);
72   }
73 
address(const_reference x)74   inline const_pointer address(const_reference x) const noexcept {
75     return std::addressof(x);
76   }
77 
78   inline pointer allocate(
79       size_type n,
80       typename AlignedAllocator<void, Alignment>::const_pointer hint = 0) {
81 #if defined(_WIN32)
82     void* memory = nullptr;
83     memory = _aligned_malloc(n * sizeof(T), Alignment);
84     if (memory == 0) {
85 #if !defined(__GNUC__) && !defined(_MSC_VER) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
86       throw std::bad_alloc();
87 #endif
88     }
89 #elif defined(__ANDROID__) || defined(__CYGWIN__)
90     void* memory = memalign(Alignment, n * sizeof(T));
91     if (memory == 0) {
92 #if !defined(__GNUC__) || defined(__EXCEPTIONS)
93       throw std::bad_alloc();
94 #endif
95     }
96 #else
97     void* memory = nullptr;
98     if (posix_memalign(&memory, Alignment, n * sizeof(T)) != 0) {
99 #if !defined(__GNUC__) || defined(__EXCEPTIONS)
100       throw std::bad_alloc();
101 #endif
102     }
103 #endif
104     return static_cast<pointer>(memory);
105   }
106 
deallocate(pointer p,size_type n)107   inline void deallocate(pointer p, size_type n) noexcept {
108 #if defined(_WIN32)
109     _aligned_free(static_cast<void*>(p));
110 #else
111     free(static_cast<void*>(p));
112 #endif
113   }
114 
115   template <class U, class... Args>
construct(U * p,Args &&...args)116   inline void construct(U* p, Args&&... args) {
117     ::new (static_cast<void*>(p)) U(std::forward<Args>(args)...);
118   }
119 
120   template <class U>
destroy(U * p)121   inline void destroy(U* p) {
122     p->~U();
123   }
124 };
125