File indexing completed on 2024-04-06 12:13:12
0001 #ifndef FWCore_Utilities_SoATuple_h
0002 #define FWCore_Utilities_SoATuple_h
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087 #include <algorithm>
0088 #include <tuple>
0089 #include <cassert>
0090 #include <utility>
0091
0092
0093 #include "FWCore/Utilities/interface/SoATupleHelper.h"
0094 #include "FWCore/Utilities/interface/GCCPrerequisite.h"
0095
0096
0097
0098 namespace edm {
0099
0100
0101 using edm::soahelper::Aligned;
0102
0103
0104 template <typename T>
0105 using AlignedVec = Aligned<T, 16>;
0106
0107 template <typename... Args>
0108 class SoATuple {
0109 public:
0110 typedef typename std::tuple<Args...> element;
0111
0112 SoATuple() : m_size(0), m_reserved(0) {
0113 for (auto& v : m_values) {
0114 v = nullptr;
0115 }
0116 }
0117 SoATuple(const SoATuple<Args...>& iOther) : m_size(0), m_reserved(0) {
0118 for (auto& v : m_values) {
0119 v = nullptr;
0120 }
0121 reserve(iOther.m_size);
0122 soahelper::SoATupleHelper<sizeof...(Args), Args...>::copyToNew(
0123 static_cast<char*>(m_values[0]), iOther.m_size, m_reserved, iOther.m_values, m_values);
0124 m_size = iOther.m_size;
0125 }
0126
0127 SoATuple(SoATuple<Args...>&& iOther) : m_size(0), m_reserved(0) {
0128 for (auto& v : m_values) {
0129 v = nullptr;
0130 }
0131 this->swap(iOther);
0132 }
0133
0134 const SoATuple<Args...>& operator=(const SoATuple<Args...>& iRHS) {
0135 SoATuple<Args...> temp(iRHS);
0136 this->swap(temp);
0137 return *this;
0138 }
0139
0140 SoATuple<Args...>& operator=(SoATuple<Args...>&& iRHS) {
0141 SoATuple<Args...> temp(std::move(iRHS));
0142 this->swap(temp);
0143 return *this;
0144 }
0145
0146 ~SoATuple() {
0147 soahelper::SoATupleHelper<sizeof...(Args), Args...>::destroy(m_values, m_size);
0148 typedef std::aligned_storage<soahelper::SoATupleHelper<sizeof...(Args), Args...>::max_alignment,
0149 soahelper::SoATupleHelper<sizeof...(Args), Args...>::max_alignment>
0150 AlignedType;
0151
0152 delete[] static_cast<AlignedType*>(m_values[0]);
0153 }
0154
0155
0156 size_t size() const { return m_size; }
0157 size_t capacity() const { return m_reserved; }
0158
0159
0160 template <unsigned int I>
0161 typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type const& get(
0162 unsigned int iIndex) const {
0163 typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type
0164 ReturnType;
0165 return *(static_cast<ReturnType const*>(m_values[I]) + iIndex);
0166 }
0167
0168
0169 template <unsigned int I>
0170 typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type const* begin()
0171 const {
0172 typedef soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type> Helper;
0173 typedef typename Helper::Type ReturnType;
0174 #if GCC_PREREQUISITE(4, 7, 0)
0175 return static_cast<ReturnType const*>(__builtin_assume_aligned(m_values[I], Helper::kAlignment));
0176 #else
0177 return static_cast<ReturnType const*>(m_values[I]);
0178 #endif
0179 }
0180
0181 template <unsigned int I>
0182 typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type const* end()
0183 const {
0184 typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type
0185 ReturnType;
0186 return static_cast<ReturnType const*>(m_values[I]) + m_size;
0187 }
0188
0189
0190
0191 void reserve(unsigned int iToSize) {
0192 if (iToSize > m_reserved) {
0193 changeSize(iToSize);
0194 }
0195 }
0196
0197
0198 void shrink_to_fit() {
0199 if (m_reserved > m_size) {
0200 changeSize(m_size);
0201 }
0202 }
0203
0204
0205 void push_back(element const& values) {
0206 if (size() + 1 > capacity()) {
0207 reserve(size() * 2 + 1);
0208 }
0209 soahelper::SoATupleHelper<sizeof...(Args), Args...>::push_back(m_values, m_size, values);
0210 ++m_size;
0211 }
0212
0213
0214 template <typename... FArgs>
0215 void emplace_back(FArgs&&... values) {
0216 if (size() + 1 > capacity()) {
0217 reserve(size() * 2 + 1);
0218 }
0219 soahelper::SoATupleHelper<sizeof...(Args), Args...>::emplace_back(
0220 m_values, m_size, std::forward<FArgs>(values)...);
0221 ++m_size;
0222 }
0223
0224
0225 template <unsigned int I>
0226 typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type& get(
0227 unsigned int iIndex) {
0228 typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type
0229 ReturnType;
0230 return *(static_cast<ReturnType*>(m_values[I]) + iIndex);
0231 }
0232
0233
0234 template <unsigned int I>
0235 typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type* begin() {
0236 typedef soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type> Helper;
0237 typedef typename Helper::Type ReturnType;
0238 #if GCC_PREREQUISITE(4, 7, 0)
0239 return static_cast<ReturnType*>(__builtin_assume_aligned(m_values[I], Helper::kAlignment));
0240 #else
0241 return static_cast<ReturnType*>(m_values[I]);
0242 #endif
0243 }
0244
0245 template <unsigned int I>
0246 typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type* end() {
0247 typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type
0248 ReturnType;
0249 return static_cast<ReturnType*>(m_values[I]) + m_size;
0250 }
0251
0252 void swap(SoATuple<Args...>& iOther) {
0253 std::swap(m_size, iOther.m_size);
0254 std::swap(m_reserved, iOther.m_reserved);
0255 for (unsigned int i = 0; i < sizeof...(Args); ++i) {
0256 std::swap(m_values[i], iOther.m_values[i]);
0257 }
0258 }
0259
0260 private:
0261 void changeSize(unsigned int iToSize) {
0262 assert(m_size <= iToSize);
0263 const size_t memoryNeededInBytes = soahelper::SoATupleHelper<sizeof...(Args), Args...>::spaceNeededFor(iToSize);
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273 const std::size_t max_alignment = soahelper::SoATupleHelper<sizeof...(Args), Args...>::max_alignment;
0274 typedef std::aligned_storage<soahelper::SoATupleHelper<sizeof...(Args), Args...>::max_alignment,
0275 soahelper::SoATupleHelper<sizeof...(Args), Args...>::max_alignment>
0276 AlignedType;
0277
0278 const size_t itemsNeeded = (memoryNeededInBytes + max_alignment - 1) / sizeof(AlignedType);
0279 char* newMemory = static_cast<char*>(static_cast<void*>(new AlignedType[itemsNeeded]));
0280 void* oldMemory = m_values[0];
0281 soahelper::SoATupleHelper<sizeof...(Args), Args...>::moveToNew(newMemory, m_size, iToSize, m_values);
0282 m_reserved = iToSize;
0283 delete[] static_cast<AlignedType*>(oldMemory);
0284 }
0285
0286
0287
0288 void* m_values[sizeof...(Args)];
0289 size_t m_size;
0290 size_t m_reserved;
0291 };
0292 }
0293
0294 #endif