1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef AlignedTArray_h__ 8 #define AlignedTArray_h__ 9 10 #include "mozilla/Alignment.h" 11 #include "nsTArray.h" 12 13 /** 14 * E: element type, must be a POD type. 15 * N: N bytes alignment for the first element, defaults to 32 16 * S: S bytes of inline storage 17 */ 18 template <typename E, int S, int N = 32> 19 class AlignedAutoTArray : private AutoTArray<E, S + N> { 20 static_assert((N & (N - 1)) == 0, "N must be power of 2"); 21 typedef AutoTArray<E, S + N> base_type; 22 23 public: 24 typedef E elem_type; 25 typedef typename base_type::size_type size_type; 26 typedef typename base_type::index_type index_type; 27 28 AlignedAutoTArray() = default; AlignedAutoTArray(size_type capacity)29 explicit AlignedAutoTArray(size_type capacity) 30 : base_type(capacity + sExtra) {} Elements()31 elem_type* Elements() { return getAligned(base_type::Elements()); } Elements()32 const elem_type* Elements() const { 33 return getAligned(base_type::Elements()); 34 } 35 elem_type& operator[](index_type i) { return Elements()[i]; } 36 const elem_type& operator[](index_type i) const { return Elements()[i]; } 37 SetLength(size_type newLen)38 void SetLength(size_type newLen) { base_type::SetLength(newLen + sExtra); } 39 SetLength(size_type newLen,const mozilla::fallible_t &)40 [[nodiscard]] bool SetLength(size_type newLen, const mozilla::fallible_t&) { 41 return base_type::SetLength(newLen + sExtra, mozilla::fallible); 42 } 43 Length()44 size_type Length() const { 45 return base_type::Length() <= sExtra ? 0 : base_type::Length() - sExtra; 46 } 47 48 using base_type::ShallowSizeOfExcludingThis; 49 using base_type::ShallowSizeOfIncludingThis; 50 51 private: 52 AlignedAutoTArray(const AlignedAutoTArray& other) = delete; 53 void operator=(const AlignedAutoTArray& other) = delete; 54 55 static const size_type sPadding = 56 N <= MOZ_ALIGNOF(E) ? 0 : N - MOZ_ALIGNOF(E); 57 static const size_type sExtra = (sPadding + sizeof(E) - 1) / sizeof(E); 58 59 template <typename U> getAligned(U * p)60 static U* getAligned(U* p) { 61 return reinterpret_cast<U*>(((uintptr_t)p + N - 1) & ~(N - 1)); 62 } 63 }; 64 65 /** 66 * E: element type, must be a POD type. 67 * N: N bytes alignment for the first element, defaults to 32 68 */ 69 template <typename E, int N = 32> 70 class AlignedTArray : private nsTArray_Impl<E, nsTArrayInfallibleAllocator> { 71 static_assert((N & (N - 1)) == 0, "N must be power of 2"); 72 typedef nsTArray_Impl<E, nsTArrayInfallibleAllocator> base_type; 73 74 public: 75 typedef E elem_type; 76 typedef typename base_type::size_type size_type; 77 typedef typename base_type::index_type index_type; 78 79 AlignedTArray() = default; AlignedTArray(size_type capacity)80 explicit AlignedTArray(size_type capacity) : base_type(capacity + sExtra) {} Elements()81 elem_type* Elements() { return getAligned(base_type::Elements()); } Elements()82 const elem_type* Elements() const { 83 return getAligned(base_type::Elements()); 84 } 85 elem_type& operator[](index_type i) { return Elements()[i]; } 86 const elem_type& operator[](index_type i) const { return Elements()[i]; } 87 SetLength(size_type newLen)88 void SetLength(size_type newLen) { base_type::SetLength(newLen + sExtra); } 89 SetLength(size_type newLen,const mozilla::fallible_t &)90 [[nodiscard]] bool SetLength(size_type newLen, const mozilla::fallible_t&) { 91 return base_type::SetLength(newLen + sExtra, mozilla::fallible); 92 } 93 Length()94 size_type Length() const { 95 return base_type::Length() <= sExtra ? 0 : base_type::Length() - sExtra; 96 } 97 98 using base_type::ShallowSizeOfExcludingThis; 99 using base_type::ShallowSizeOfIncludingThis; 100 101 private: 102 AlignedTArray(const AlignedTArray& other) = delete; 103 void operator=(const AlignedTArray& other) = delete; 104 105 static const size_type sPadding = 106 N <= MOZ_ALIGNOF(E) ? 0 : N - MOZ_ALIGNOF(E); 107 static const size_type sExtra = (sPadding + sizeof(E) - 1) / sizeof(E); 108 109 template <typename U> getAligned(U * p)110 static U* getAligned(U* p) { 111 return reinterpret_cast<U*>(((uintptr_t)p + N - 1) & ~(N - 1)); 112 } 113 }; 114 115 #endif // AlignedTArray_h__ 116