00001 #ifndef FWCore_Utilities_SoATupleHelper_h
00002 #define FWCore_Utilities_SoATupleHelper_h
00003
00004
00005
00006
00007
00016
00017
00018
00019
00020
00021
00022
00023 #include <tuple>
00024 #include <algorithm>
00025
00026
00027
00028
00029 namespace edm {
00030 namespace soahelper {
00031
00034 constexpr unsigned int padding_needed(size_t iSizeSoFar, unsigned int iBoundary) {
00035 return (iBoundary - iSizeSoFar % iBoundary) % iBoundary;
00036 }
00037
00043 template<unsigned int I, unsigned int J, typename Ret, typename... Args>
00044 struct arg_puller;
00045
00047 template<unsigned int I, unsigned int J, typename Ret, typename F, typename... Args>
00048 struct arg_puller<I,J,Ret,F, Args...> {
00049 static Ret pull(F const&, const Args&... args) {
00050 return arg_puller<I+1, J,Ret,Args...>::pull(args...);
00051 }
00052 };
00053
00055 template<unsigned int I, typename Ret, typename F, typename... Args>
00056 struct arg_puller<I,I,Ret,F, Args...> {
00057 static Ret pull(F const& iV, const Args&...) {
00058 return iV;
00059 }
00060 };
00061
00066 template<typename T, unsigned int ALIGNMENT>
00067 struct Aligned {
00068 static const unsigned int kAlignment = ALIGNMENT;
00069 typedef T Type;
00070 };
00071
00072
00077 template<typename T>
00078 struct AlignmentHelper {
00079 static const std::size_t kAlignment = alignof(T);
00080 typedef T Type;
00081 };
00082
00086 template<typename T, unsigned int ALIGNMENT>
00087 struct AlignmentHelper<Aligned<T,ALIGNMENT>> {
00088 static const std::size_t kAlignment = ALIGNMENT;
00089 typedef T Type;
00090 };
00091
00096 template<unsigned int I, typename... Args>
00097 struct SoATupleHelper
00098 {
00099 typedef AlignmentHelper<typename std::tuple_element<I-1, std::tuple<Args...>>::type> AlignmentInfo;
00100 typedef typename AlignmentInfo::Type Type;
00101 typedef SoATupleHelper<I-1,Args...> NextHelper;
00102
00103 static const std::size_t max_alignment = AlignmentInfo::kAlignment > NextHelper::max_alignment ?
00104 AlignmentInfo::kAlignment: NextHelper::max_alignment;
00105
00106
00107 static size_t moveToNew(char* iNewMemory, size_t iSize, size_t iReserve, void** oToSet);
00108 static size_t copyToNew(char* iNewMemory, size_t iSize, size_t iReserve, void* const* iFrom, void** oToSet);
00109 static size_t spaceNeededFor(unsigned int iNElements);
00110 static void push_back(void** iToSet, size_t iSize, std::tuple<Args...> const& iValues);
00111 template<typename... FArgs>
00112 static void emplace_back(void** iToSet, size_t iSize, FArgs... iValues);
00113 static void destroy(void** iToSet, size_t iSize);
00114
00115
00116 SoATupleHelper(const SoATupleHelper&) = delete;
00117
00118 const SoATupleHelper& operator=(const SoATupleHelper&) = delete;
00119
00120 };
00121
00122
00123 template<typename... Args>
00124 struct SoATupleHelper<0,Args...> {
00125 static const std::size_t max_alignment = 0;
00126 static void destroy(void** , size_t ) {
00127 }
00128
00129 static void push_back(void** , size_t , std::tuple<Args...> const& ) {
00130 }
00131
00132 template<typename... FArgs>
00133 static void emplace_back(void** iToSet, size_t iSize, FArgs... iValues) {}
00134
00135 static size_t spaceNeededFor(unsigned int ) {
00136 return 0;
00137 }
00138
00139 static size_t moveToNew(char* , size_t , size_t , void** ) {
00140 return 0;
00141 }
00142
00143 static size_t copyToNew(char* , size_t , size_t , void* const* , void** ) {
00144 return 0;
00145 }
00146 };
00147
00148 template<unsigned int I, typename... Args>
00149 size_t SoATupleHelper<I,Args...>::moveToNew(char* iNewMemory, size_t iSize, size_t iReserve, void** oToSet) {
00150 size_t usedSoFar = NextHelper::moveToNew(iNewMemory,iSize, iReserve, oToSet);
00151
00152
00153 const unsigned int boundary = AlignmentInfo::kAlignment;
00154
00155 Type* newStart = reinterpret_cast<Type*>(iNewMemory+usedSoFar+padding_needed(usedSoFar,boundary));
00156
00157 void** oldStart = oToSet+I-1;
00158
00159 Type* oldValues = static_cast<Type*>(*oldStart);
00160 if(oldValues != nullptr ) {
00161 auto ptr = newStart;
00162 for(auto it = oldValues; it != oldValues+iSize; ++it,++ptr) {
00163 new (ptr) Type(std::move(*it));
00164 }
00165 for(auto it = oldValues; it != oldValues+iSize; ++it) {
00166 it->~Type();
00167 }
00168 }
00169 *oldStart = newStart;
00170 unsigned int additionalSize = padding_needed(usedSoFar,boundary) + iReserve*sizeof(Type);
00171 return usedSoFar+additionalSize;
00172 }
00173
00174 template<unsigned int I, typename... Args>
00175 size_t SoATupleHelper<I,Args...>::copyToNew(char* iNewMemory, size_t iSize, size_t iReserve, void* const* iFrom, void** oToSet) {
00176 size_t usedSoFar = NextHelper::copyToNew(iNewMemory,iSize, iReserve, iFrom, oToSet);
00177
00178
00179 const unsigned int boundary = AlignmentInfo::kAlignment;
00180
00181 Type* newStart = reinterpret_cast<Type*>(iNewMemory+usedSoFar+padding_needed(usedSoFar,boundary));
00182
00183 void* const* oldStart = iFrom+I-1;
00184
00185 Type* oldValues = static_cast<Type*>(*oldStart);
00186 if(oldValues != nullptr ) {
00187 auto ptr = newStart;
00188 for(auto it = oldValues; it != oldValues+iSize; ++it,++ptr) {
00189 new (ptr) Type(*it);
00190 }
00191 }
00192 *(oToSet+I-1) = newStart;
00193 unsigned int additionalSize = padding_needed(usedSoFar,boundary) + iReserve*sizeof(Type);
00194 return usedSoFar+additionalSize;
00195 }
00196
00197
00198 template<unsigned int I, typename... Args>
00199 size_t SoATupleHelper<I,Args...>::spaceNeededFor(unsigned int iNElements) {
00200 size_t usedSoFar = NextHelper::spaceNeededFor(iNElements);
00201 const unsigned int boundary = AlignmentInfo::kAlignment;
00202 unsigned int additionalSize = padding_needed(usedSoFar,boundary) + iNElements*sizeof(Type);
00203 return usedSoFar+additionalSize;
00204 }
00205
00206 template<unsigned int I, typename... Args>
00207 void SoATupleHelper<I,Args...>::push_back(void** iToSet, size_t iSize, std::tuple<Args...> const& iValues) {
00208 new (static_cast<Type*>(*(iToSet+I-1))+iSize) Type(std::get<I-1>(iValues));
00209
00210 NextHelper::push_back(iToSet,iSize,iValues);
00211 }
00212
00213 template<unsigned int I, typename... Args>
00214 template<typename ... FArgs>
00215 void SoATupleHelper<I,Args...>::emplace_back(void** iToSet, size_t iSize, FArgs... iValues) {
00216 new (static_cast<Type*>(*(iToSet+I-1))+iSize) Type(arg_puller<0,I-1,Type const&, FArgs...>::pull(std::forward<FArgs>(iValues)...));
00217
00218 NextHelper::emplace_back(iToSet,iSize,std::forward<FArgs>(iValues)...);
00219 }
00220
00221 template<unsigned int I, typename... Args>
00222 void SoATupleHelper<I,Args...>::destroy(void** iToSet, size_t iSize) {
00223 void** start = iToSet+I-1;
00224 Type* values = static_cast<Type*>(*start);
00225
00226 for(auto it = values; it != values+iSize; ++it) {
00227 it->~Type();
00228 }
00229
00230 NextHelper::destroy(iToSet,iSize);
00231 }
00232
00233 }
00234 }
00235
00236 #endif