blob: bb724eaa5ba9ac0704eb6370154c96238a9782af [file] [log] [blame]
XNNPACK Teamb455b122019-09-27 18:10:33 -07001// 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 <type_traits>
10#include <utility>
11
12#include <stdlib.h>
13
Marat Dukhan78583c72020-04-26 22:00:43 -070014#if defined(__ANDROID__) || defined(_WIN32) || defined(__CYGWIN__)
15 #include <malloc.h>
16#endif
17
18
XNNPACK Teamb455b122019-09-27 18:10:33 -070019template <typename T, size_t Alignment>
20class AlignedAllocator;
21
22template <size_t Alignment>
23class AlignedAllocator<void, Alignment> {
24 public:
25 typedef void* pointer;
26 typedef const void* const_pointer;
27 typedef void value_type;
28
29 template <class U>
30 struct rebind {
31 typedef AlignedAllocator<U, Alignment> other;
32 };
33};
34
35template <typename T, size_t Alignment>
36class AlignedAllocator {
37 public:
38 typedef T value_type;
39 typedef T* pointer;
40 typedef const T* const_pointer;
41 typedef T& reference;
42 typedef const T& const_reference;
43 typedef size_t size_type;
44 typedef ptrdiff_t difference_type;
45
46#if __cplusplus >= 201402L
47 typedef std::true_type propagate_on_container_move_assignment;
48#endif
49
50 template <class U>
51 struct rebind {
52 typedef AlignedAllocator<U, Alignment> other;
53 };
54
55 public:
56 inline AlignedAllocator() noexcept {}
57
58 template <class U>
59 inline AlignedAllocator(
60 const AlignedAllocator<U, Alignment>& other) noexcept {}
61
62 inline size_type max_size() const noexcept {
63 return (std::numeric_limits<size_type>::max() - size_type(Alignment)) /
64 sizeof(T);
65 }
66
67 inline pointer address(reference x) const noexcept {
68 return std::addressof(x);
69 }
70
71 inline const_pointer address(const_reference x) const noexcept {
72 return std::addressof(x);
73 }
74
75 inline pointer allocate(
76 size_type n,
77 typename AlignedAllocator<void, Alignment>::const_pointer hint = 0) {
Marat Dukhan78583c72020-04-26 22:00:43 -070078#if defined(_WIN32)
Yasuhiro Matsumoto462be052020-02-29 13:41:14 +090079 void* memory = nullptr;
80 memory = _aligned_malloc(n * sizeof(T), Alignment);
81 if (memory == 0) {
Yasuhiro Matsumotodac1a0e2020-02-29 14:31:49 +090082#if !defined(__GNUC__) && !defined(_MSC_VER) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
Yasuhiro Matsumoto462be052020-02-29 13:41:14 +090083 throw std::bad_alloc();
84#endif
85 }
Marat Dukhan78583c72020-04-26 22:00:43 -070086#elif defined(__ANDROID__) || defined(__CYGWIN__)
87 void* memory = memalign(Alignment, n * sizeof(T));
88 if (memory == 0) {
89#if !defined(__GNUC__) || defined(__EXCEPTIONS)
90 throw std::bad_alloc();
91#endif
92 }
XNNPACK Teamb455b122019-09-27 18:10:33 -070093#else
94 void* memory = nullptr;
95 if (posix_memalign(&memory, Alignment, n * sizeof(T)) != 0) {
96#if !defined(__GNUC__) || defined(__EXCEPTIONS)
97 throw std::bad_alloc();
98#endif
99 }
100#endif
101 return static_cast<pointer>(memory);
102 }
103
104 inline void deallocate(pointer p, size_type n) noexcept {
Marat Dukhanc2cfb972020-04-13 10:17:06 -0700105#if defined(_WIN32)
106 _aligned_free(static_cast<void*>(p));
107#else
XNNPACK Teamb455b122019-09-27 18:10:33 -0700108 free(static_cast<void*>(p));
Marat Dukhanc2cfb972020-04-13 10:17:06 -0700109#endif
XNNPACK Teamb455b122019-09-27 18:10:33 -0700110 }
111
112 template <class U, class... Args>
113 inline void construct(U* p, Args&&... args) {
114 ::new (static_cast<void*>(p)) U(std::forward<Args>(args)...);
115 }
116
117 template <class U>
118 inline void destroy(U* p) {
119 p->~U();
120 }
121};