File indexing completed on 2024-04-06 12:13:13
0001 #ifndef FWCore_Utilities_SoATupleHelper_h
0002 #define FWCore_Utilities_SoATupleHelper_h
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include <tuple>
0023 #include <algorithm>
0024
0025
0026
0027
0028 namespace edm {
0029 namespace soahelper {
0030
0031
0032
0033 constexpr unsigned int padding_needed(size_t iSizeSoFar, unsigned int iBoundary) {
0034 return (iBoundary - iSizeSoFar % iBoundary) % iBoundary;
0035 }
0036
0037
0038
0039
0040
0041
0042 template <unsigned int I, unsigned int J, typename Ret, typename... Args>
0043 struct arg_puller;
0044
0045
0046 template <unsigned int I, unsigned int J, typename Ret, typename F, typename... Args>
0047 struct arg_puller<I, J, Ret, F, Args...> {
0048 static Ret pull(F const&, const Args&... args) { return arg_puller<I + 1, J, Ret, Args...>::pull(args...); }
0049 };
0050
0051
0052 template <unsigned int I, typename Ret, typename F, typename... Args>
0053 struct arg_puller<I, I, Ret, F, Args...> {
0054 static Ret pull(F const& iV, const Args&...) { return iV; }
0055 };
0056
0057
0058
0059
0060
0061 template <typename T, unsigned int ALIGNMENT>
0062 struct Aligned {
0063 static const unsigned int kAlignment = ALIGNMENT;
0064 typedef T Type;
0065 };
0066
0067
0068
0069
0070
0071 template <typename T>
0072 struct AlignmentHelper {
0073 static const std::size_t kAlignment = alignof(T);
0074 typedef T Type;
0075 };
0076
0077
0078
0079
0080 template <typename T, unsigned int ALIGNMENT>
0081 struct AlignmentHelper<Aligned<T, ALIGNMENT>> {
0082 static const std::size_t kAlignment = ALIGNMENT;
0083 typedef T Type;
0084 };
0085
0086
0087
0088
0089
0090 template <unsigned int I, typename... Args>
0091 struct SoATupleHelper {
0092 typedef AlignmentHelper<typename std::tuple_element<I - 1, std::tuple<Args...>>::type> AlignmentInfo;
0093 typedef typename AlignmentInfo::Type Type;
0094 typedef SoATupleHelper<I - 1, Args...> NextHelper;
0095
0096 static const std::size_t max_alignment =
0097 AlignmentInfo::kAlignment > NextHelper::max_alignment ? AlignmentInfo::kAlignment : NextHelper::max_alignment;
0098
0099
0100 static size_t moveToNew(char* iNewMemory, size_t iSize, size_t iReserve, void** oToSet);
0101 static size_t copyToNew(char* iNewMemory, size_t iSize, size_t iReserve, void* const* iFrom, void** oToSet);
0102 static size_t spaceNeededFor(unsigned int iNElements);
0103 static void push_back(void** iToSet, size_t iSize, std::tuple<Args...> const& iValues);
0104 template <typename... FArgs>
0105 static void emplace_back(void** iToSet, size_t iSize, FArgs... iValues);
0106 static void destroy(void** iToSet, size_t iSize);
0107
0108
0109 SoATupleHelper(const SoATupleHelper&) = delete;
0110
0111 const SoATupleHelper& operator=(const SoATupleHelper&) = delete;
0112 };
0113
0114
0115 template <typename... Args>
0116 struct SoATupleHelper<0, Args...> {
0117 static const std::size_t max_alignment = 0;
0118 static void destroy(void** , size_t ) {}
0119
0120 static void push_back(void** , size_t , std::tuple<Args...> const& ) {}
0121
0122 template <typename... FArgs>
0123 static void emplace_back(void** iToSet, size_t iSize, FArgs... iValues) {}
0124
0125 static size_t spaceNeededFor(unsigned int ) { return 0; }
0126
0127 static size_t moveToNew(char* , size_t , size_t , void** ) {
0128 return 0;
0129 }
0130
0131 static size_t copyToNew(
0132 char* , size_t , size_t , void* const* , void** ) {
0133 return 0;
0134 }
0135 };
0136
0137 template <unsigned int I, typename... Args>
0138 size_t SoATupleHelper<I, Args...>::moveToNew(char* iNewMemory, size_t iSize, size_t iReserve, void** oToSet) {
0139 size_t usedSoFar = NextHelper::moveToNew(iNewMemory, iSize, iReserve, oToSet);
0140
0141
0142 const unsigned int boundary = AlignmentInfo::kAlignment;
0143
0144 Type* newStart = reinterpret_cast<Type*>(iNewMemory + usedSoFar + padding_needed(usedSoFar, boundary));
0145
0146 void** oldStart = oToSet + I - 1;
0147
0148 Type* oldValues = static_cast<Type*>(*oldStart);
0149 if (oldValues != nullptr) {
0150 auto ptr = newStart;
0151 for (auto it = oldValues; it != oldValues + iSize; ++it, ++ptr) {
0152 new (ptr) Type(std::move(*it));
0153 }
0154 for (auto it = oldValues; it != oldValues + iSize; ++it) {
0155 it->~Type();
0156 }
0157 }
0158 *oldStart = newStart;
0159 unsigned int additionalSize = padding_needed(usedSoFar, boundary) + iReserve * sizeof(Type);
0160 return usedSoFar + additionalSize;
0161 }
0162
0163 template <unsigned int I, typename... Args>
0164 size_t SoATupleHelper<I, Args...>::copyToNew(
0165 char* iNewMemory, size_t iSize, size_t iReserve, void* const* iFrom, void** oToSet) {
0166 size_t usedSoFar = NextHelper::copyToNew(iNewMemory, iSize, iReserve, iFrom, oToSet);
0167
0168
0169 const unsigned int boundary = AlignmentInfo::kAlignment;
0170
0171 Type* newStart = reinterpret_cast<Type*>(iNewMemory + usedSoFar + padding_needed(usedSoFar, boundary));
0172
0173 void* const* oldStart = iFrom + I - 1;
0174
0175 Type* oldValues = static_cast<Type*>(*oldStart);
0176 if (oldValues != nullptr) {
0177 auto ptr = newStart;
0178 for (auto it = oldValues; it != oldValues + iSize; ++it, ++ptr) {
0179 new (ptr) Type(*it);
0180 }
0181 }
0182 *(oToSet + I - 1) = newStart;
0183 unsigned int additionalSize = padding_needed(usedSoFar, boundary) + iReserve * sizeof(Type);
0184 return usedSoFar + additionalSize;
0185 }
0186
0187 template <unsigned int I, typename... Args>
0188 size_t SoATupleHelper<I, Args...>::spaceNeededFor(unsigned int iNElements) {
0189 size_t usedSoFar = NextHelper::spaceNeededFor(iNElements);
0190 const unsigned int boundary = AlignmentInfo::kAlignment;
0191 unsigned int additionalSize = padding_needed(usedSoFar, boundary) + iNElements * sizeof(Type);
0192 return usedSoFar + additionalSize;
0193 }
0194
0195 template <unsigned int I, typename... Args>
0196 void SoATupleHelper<I, Args...>::push_back(void** iToSet, size_t iSize, std::tuple<Args...> const& iValues) {
0197 new (static_cast<Type*>(*(iToSet + I - 1)) + iSize) Type(std::get<I - 1>(iValues));
0198
0199 NextHelper::push_back(iToSet, iSize, iValues);
0200 }
0201
0202 template <unsigned int I, typename... Args>
0203 template <typename... FArgs>
0204 void SoATupleHelper<I, Args...>::emplace_back(void** iToSet, size_t iSize, FArgs... iValues) {
0205 new (static_cast<Type*>(*(iToSet + I - 1)) + iSize)
0206 Type(arg_puller<0, I - 1, Type const&, FArgs...>::pull(std::forward<FArgs>(iValues)...));
0207
0208 NextHelper::emplace_back(iToSet, iSize, std::forward<FArgs>(iValues)...);
0209 }
0210
0211 template <unsigned int I, typename... Args>
0212 void SoATupleHelper<I, Args...>::destroy(void** iToSet, size_t iSize) {
0213 void** start = iToSet + I - 1;
0214 Type* values = static_cast<Type*>(*start);
0215
0216 for (auto it = values; it != values + iSize; ++it) {
0217 it->~Type();
0218 }
0219
0220 NextHelper::destroy(iToSet, iSize);
0221 }
0222
0223 }
0224 }
0225
0226 #endif