summaryrefslogtreecommitdiff
path: root/src/common/alignment.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/alignment.h')
-rw-r--r--src/common/alignment.h60
1 files changed, 11 insertions, 49 deletions
diff --git a/src/common/alignment.h b/src/common/alignment.h
index b37044bb6..5040043de 100644
--- a/src/common/alignment.h
+++ b/src/common/alignment.h
@@ -3,13 +3,13 @@
3#pragma once 3#pragma once
4 4
5#include <cstddef> 5#include <cstddef>
6#include <memory> 6#include <new>
7#include <type_traits> 7#include <type_traits>
8 8
9namespace Common { 9namespace Common {
10 10
11template <typename T> 11template <typename T>
12constexpr T AlignUp(T value, std::size_t size) { 12[[nodiscard]] constexpr T AlignUp(T value, std::size_t size) {
13 static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); 13 static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
14 auto mod{static_cast<T>(value % size)}; 14 auto mod{static_cast<T>(value % size)};
15 value -= mod; 15 value -= mod;
@@ -17,31 +17,31 @@ constexpr T AlignUp(T value, std::size_t size) {
17} 17}
18 18
19template <typename T> 19template <typename T>
20constexpr T AlignDown(T value, std::size_t size) { 20[[nodiscard]] constexpr T AlignDown(T value, std::size_t size) {
21 static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); 21 static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
22 return static_cast<T>(value - value % size); 22 return static_cast<T>(value - value % size);
23} 23}
24 24
25template <typename T> 25template <typename T>
26constexpr T AlignBits(T value, std::size_t align) { 26[[nodiscard]] constexpr T AlignBits(T value, std::size_t align) {
27 static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); 27 static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
28 return static_cast<T>((value + ((1ULL << align) - 1)) >> align << align); 28 return static_cast<T>((value + ((1ULL << align) - 1)) >> align << align);
29} 29}
30 30
31template <typename T> 31template <typename T>
32constexpr bool Is4KBAligned(T value) { 32[[nodiscard]] constexpr bool Is4KBAligned(T value) {
33 static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); 33 static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
34 return (value & 0xFFF) == 0; 34 return (value & 0xFFF) == 0;
35} 35}
36 36
37template <typename T> 37template <typename T>
38constexpr bool IsWordAligned(T value) { 38[[nodiscard]] constexpr bool IsWordAligned(T value) {
39 static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); 39 static_assert(std::is_unsigned_v<T>, "T must be an unsigned value.");
40 return (value & 0b11) == 0; 40 return (value & 0b11) == 0;
41} 41}
42 42
43template <typename T> 43template <typename T>
44constexpr bool IsAligned(T value, std::size_t alignment) { 44[[nodiscard]] constexpr bool IsAligned(T value, std::size_t alignment) {
45 using U = typename std::make_unsigned<T>::type; 45 using U = typename std::make_unsigned<T>::type;
46 const U mask = static_cast<U>(alignment - 1); 46 const U mask = static_cast<U>(alignment - 1);
47 return (value & mask) == 0; 47 return (value & mask) == 0;
@@ -54,66 +54,28 @@ public:
54 using size_type = std::size_t; 54 using size_type = std::size_t;
55 using difference_type = std::ptrdiff_t; 55 using difference_type = std::ptrdiff_t;
56 56
57 using pointer = T*;
58 using const_pointer = const T*;
59
60 using reference = T&;
61 using const_reference = const T&;
62
63 using propagate_on_container_copy_assignment = std::true_type; 57 using propagate_on_container_copy_assignment = std::true_type;
64 using propagate_on_container_move_assignment = std::true_type; 58 using propagate_on_container_move_assignment = std::true_type;
65 using propagate_on_container_swap = std::true_type; 59 using propagate_on_container_swap = std::true_type;
66 using is_always_equal = std::true_type; 60 using is_always_equal = std::true_type;
67 61
68public:
69 constexpr AlignmentAllocator() noexcept = default; 62 constexpr AlignmentAllocator() noexcept = default;
70 63
71 template <typename T2> 64 template <typename T2>
72 constexpr AlignmentAllocator(const AlignmentAllocator<T2, Align>&) noexcept {} 65 constexpr AlignmentAllocator(const AlignmentAllocator<T2, Align>&) noexcept {}
73 66
74 pointer address(reference r) noexcept { 67 [[nodiscard]] T* allocate(size_type n) {
75 return std::addressof(r); 68 return static_cast<T*>(::operator new (n * sizeof(T), std::align_val_t{Align}));
76 }
77
78 const_pointer address(const_reference r) const noexcept {
79 return std::addressof(r);
80 }
81
82 pointer allocate(size_type n) {
83 return static_cast<pointer>(::operator new (n, std::align_val_t{Align}));
84 }
85
86 void deallocate(pointer p, size_type) {
87 ::operator delete (p, std::align_val_t{Align});
88 } 69 }
89 70
90 void construct(pointer p, const value_type& wert) { 71 void deallocate(T* p, size_type n) {
91 new (p) value_type(wert); 72 ::operator delete (p, n * sizeof(T), std::align_val_t{Align});
92 }
93
94 void destroy(pointer p) {
95 p->~value_type();
96 }
97
98 size_type max_size() const noexcept {
99 return size_type(-1) / sizeof(value_type);
100 } 73 }
101 74
102 template <typename T2> 75 template <typename T2>
103 struct rebind { 76 struct rebind {
104 using other = AlignmentAllocator<T2, Align>; 77 using other = AlignmentAllocator<T2, Align>;
105 }; 78 };
106
107 bool operator!=(const AlignmentAllocator<T, Align>& other) const noexcept {
108 return !(*this == other);
109 }
110
111 // Returns true if and only if storage allocated from *this
112 // can be deallocated from other, and vice versa.
113 // Always returns true for stateless allocators.
114 bool operator==(const AlignmentAllocator<T, Align>& other) const noexcept {
115 return true;
116 }
117}; 79};
118 80
119} // namespace Common 81} // namespace Common