• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <cstddef>
8 #include <limits>
9 #include <memory>
10 #include <type_traits>
11 #include <utility>
12 
13 #include <stdlib.h>
14 
15 #if defined(__ANDROID__) || defined(_WIN32) || defined(__CYGWIN__)
16   #include <malloc.h>
17 #endif
18 
19 
20 template <typename T, size_t Alignment>
21 class AlignedAllocator;
22 
23 template <size_t Alignment>
24 class AlignedAllocator<void, Alignment> {
25  public:
26   typedef void* pointer;
27   typedef const void* const_pointer;
28   typedef void value_type;
29 
30   template <class U>
31   struct rebind {
32     typedef AlignedAllocator<U, Alignment> other;
33   };
34 };
35 
36 template <typename T, size_t Alignment>
37 class AlignedAllocator {
38  public:
39   typedef T value_type;
40   typedef T* pointer;
41   typedef const T* const_pointer;
42   typedef T& reference;
43   typedef const T& const_reference;
44   typedef size_t size_type;
45   typedef ptrdiff_t difference_type;
46 
47 #if __cplusplus >= 201402L
48   typedef std::true_type propagate_on_container_move_assignment;
49 #endif
50 
51   template <class U>
52   struct rebind {
53     typedef AlignedAllocator<U, Alignment> other;
54   };
55 
56  public:
AlignedAllocator()57   inline AlignedAllocator() noexcept {}
58 
59   template <class U>
AlignedAllocator(const AlignedAllocator<U,Alignment> & other)60   inline AlignedAllocator(
61       const AlignedAllocator<U, Alignment>& other) noexcept {}
62 
max_size()63   inline size_type max_size() const noexcept {
64     return (std::numeric_limits<size_type>::max() - size_type(Alignment)) /
65         sizeof(T);
66   }
67 
address(reference x)68   inline pointer address(reference x) const noexcept {
69     return std::addressof(x);
70   }
71 
address(const_reference x)72   inline const_pointer address(const_reference x) const noexcept {
73     return std::addressof(x);
74   }
75 
76   inline pointer allocate(
77       size_type n,
78       typename AlignedAllocator<void, Alignment>::const_pointer hint = 0) {
79 #if defined(_WIN32)
80     void* memory = nullptr;
81     memory = _aligned_malloc(n * sizeof(T), Alignment);
82     if (memory == 0) {
83 #if !defined(__GNUC__) && !defined(_MSC_VER) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
84       throw std::bad_alloc();
85 #endif
86     }
87 #elif defined(__ANDROID__) || defined(__CYGWIN__)
88     void* memory = memalign(Alignment, n * sizeof(T));
89     if (memory == 0) {
90 #if !defined(__GNUC__) || defined(__EXCEPTIONS)
91       throw std::bad_alloc();
92 #endif
93     }
94 #else
95     void* memory = nullptr;
96     if (posix_memalign(&memory, Alignment, n * sizeof(T)) != 0) {
97 #if !defined(__GNUC__) || defined(__EXCEPTIONS)
98       throw std::bad_alloc();
99 #endif
100     }
101 #endif
102     return static_cast<pointer>(memory);
103   }
104 
deallocate(pointer p,size_type n)105   inline void deallocate(pointer p, size_type n) noexcept {
106 #if defined(_WIN32)
107     _aligned_free(static_cast<void*>(p));
108 #else
109     free(static_cast<void*>(p));
110 #endif
111   }
112 
113   template <class U, class... Args>
construct(U * p,Args &&...args)114   inline void construct(U* p, Args&&... args) {
115     ::new (static_cast<void*>(p)) U(std::forward<Args>(args)...);
116   }
117 
118   template <class U>
destroy(U * p)119   inline void destroy(U* p) {
120     p->~U();
121   }
122 };
123