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