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