CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/FWCore/Utilities/interface/SoATupleHelper.h

Go to the documentation of this file.
00001 #ifndef FWCore_Utilities_SoATupleHelper_h
00002 #define FWCore_Utilities_SoATupleHelper_h
00003 // -*- C++ -*-
00004 //
00005 // Package:     Package
00006 // Class  :     SoATupleHelper
00007 // 
00016 //
00017 // Original Author:  Chris Jones
00018 //         Created:  Tue, 16 Apr 2013 21:06:08 GMT
00019 // $Id: SoATupleHelper.h,v 1.4 2013/04/23 20:07:48 chrjones Exp $
00020 //
00021 
00022 // system include files
00023 #include <tuple>
00024 #include <algorithm>
00025 
00026 // user include files
00027 
00028 // forward declarations
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       // ---------- static member functions --------------------
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       // ---------- member functions ---------------------------
00116       SoATupleHelper(const SoATupleHelper&) = delete; // stop default
00117       
00118       const SoATupleHelper& operator=(const SoATupleHelper&) = delete; // stop default
00119       
00120     };
00121     
00122     //Specialization used to stop recursion
00123     template<typename... Args>
00124     struct SoATupleHelper<0,Args...> {
00125       static const std::size_t max_alignment = 0;
00126       static void destroy(void** /*iToSet*/, size_t /*iSize*/) {
00127       }
00128       
00129       static void push_back(void** /*iToSet*/, size_t /*iSize*/, std::tuple<Args...> const& /*values*/) {
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 /*iNElements*/) {
00136         return 0;
00137       }
00138       
00139       static size_t moveToNew(char* /*iNewMemory*/, size_t /*iSize*/, size_t /*iReserve*/, void** /*oToSet*/) {
00140         return 0;
00141       }
00142       
00143       static size_t copyToNew(char* /*iNewMemory*/, size_t /*iSize*/, size_t /*iReserve*/, void* const* /*iFrom*/, void** /*oToSet*/) {
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       //find new start
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       //find new start
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