00001 #ifndef FWCore_Utilities_SoATuple_h
00002 #define FWCore_Utilities_SoATuple_h
00003
00004
00005
00006
00007
00081
00082
00083
00084
00085
00086
00087
00088 #include <algorithm>
00089 #include <tuple>
00090 #include <cassert>
00091
00092
00093 #include "FWCore/Utilities/interface/SoATupleHelper.h"
00094 #include "FWCore/Utilities/interface/GCCPrerequisite.h"
00095
00096
00097
00098
00099 namespace edm {
00100
00101
00102 using edm::soahelper::Aligned;
00103
00104
00105 template<typename T> using AlignedVec = Aligned<T,16>;
00106
00107 template <typename... Args>
00108 class SoATuple
00109 {
00110
00111 public:
00112 typedef typename std::tuple<Args...> element;
00113
00114 SoATuple(): m_size(0),m_reserved(0){
00115 for(auto& v : m_values) {
00116 v = nullptr;
00117 }
00118 }
00119 SoATuple(const SoATuple<Args...>& iOther):m_size(0),m_reserved(0) {
00120 for(auto& v : m_values) {
00121 v = nullptr;
00122 }
00123 reserve(iOther.m_size);
00124 soahelper::SoATupleHelper<sizeof...(Args),Args...>::copyToNew(static_cast<char*>(m_values[0]),iOther.m_size,m_reserved,iOther.m_values,m_values);
00125 m_size = iOther.m_size;
00126 }
00127
00128 SoATuple(SoATuple<Args...>&& iOther):m_size(0),m_reserved(0) {
00129 for(auto& v : m_values) {
00130 v = nullptr;
00131 }
00132 this->swap(iOther);
00133 }
00134
00135 const SoATuple<Args...>& operator=(const SoATuple<Args...>& iRHS) {
00136 SoATuple<Args...> temp(iRHS);
00137 this->swap(temp);
00138 return *this;
00139 }
00140
00141 ~SoATuple() {
00142 soahelper::SoATupleHelper<sizeof...(Args),Args...>::destroy(m_values,m_size);
00143 typedef std::aligned_storage<soahelper::SoATupleHelper<sizeof...(Args),Args...>::max_alignment,
00144 soahelper::SoATupleHelper<sizeof...(Args),Args...>::max_alignment> AlignedType;
00145
00146 delete [] static_cast<AlignedType*>(m_values[0]);
00147 }
00148
00149
00150 size_t size() const { return m_size;}
00151 size_t capacity() const {return m_reserved;}
00152
00154 template<unsigned int I>
00155 typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type const& get(unsigned int iIndex) const {
00156 typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type ReturnType;
00157 return *(static_cast<ReturnType const*>(m_values[I])+iIndex);
00158 }
00159
00161 template<unsigned int I>
00162 typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type const* begin() const {
00163 typedef soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type> Helper;
00164 typedef typename Helper::Type ReturnType;
00165 #if GCC_PREREQUISITE(4,7,0)
00166 return static_cast<ReturnType const*>(__builtin_assume_aligned(m_values[I],Helper::kAlignment));
00167 #else
00168 return static_cast<ReturnType const*>(m_values[I]);
00169 #endif
00170 }
00172 template<unsigned int I>
00173 typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type const* end() const {
00174 typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type ReturnType;
00175 return static_cast<ReturnType const*>(m_values[I])+m_size;
00176 }
00177
00178
00180 void reserve(unsigned int iToSize) {
00181 if(iToSize > m_reserved) {
00182 changeSize(iToSize);
00183 }
00184 }
00185
00187 void shrink_to_fit() {
00188 if(m_reserved > m_size) {
00189 changeSize(m_size);
00190 }
00191 }
00192
00194 void push_back(element const& values) {
00195 if(size()+1>capacity()) {
00196 reserve(size()*2+1);
00197 }
00198 soahelper::SoATupleHelper<sizeof...(Args),Args...>::push_back(m_values,m_size,values);
00199 ++m_size;
00200 }
00201
00203 template< typename... FArgs>
00204 void emplace_back(FArgs&&... values) {
00205 if(size()+1>capacity()) {
00206 reserve(size()*2+1);
00207 }
00208 soahelper::SoATupleHelper<sizeof...(Args),Args...>::emplace_back(m_values,m_size,std::forward<FArgs>(values)...);
00209 ++m_size;
00210 }
00211
00213 template<unsigned int I>
00214 typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type& get(unsigned int iIndex) {
00215 typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type ReturnType;
00216 return *(static_cast<ReturnType*>(m_values[I])+iIndex);
00217 }
00218
00220 template<unsigned int I>
00221 typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type* begin() {
00222 typedef soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type> Helper;
00223 typedef typename Helper::Type ReturnType;
00224 #if GCC_PREREQUISITE(4,7,0)
00225 return static_cast<ReturnType*>(__builtin_assume_aligned(m_values[I],Helper::kAlignment));
00226 #else
00227 return static_cast<ReturnType*>(m_values[I]);
00228 #endif
00229 }
00231 template<unsigned int I>
00232 typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type* end() {
00233 typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type ReturnType;
00234 return static_cast<ReturnType*>(m_values[I])+m_size;
00235 }
00236
00237 void swap(SoATuple<Args...>& iOther) {
00238 std::swap(m_size,iOther.m_size);
00239 std::swap(m_reserved,iOther.m_reserved);
00240 for(unsigned int i=0; i<sizeof...(Args);++i) {
00241 std::swap(m_values[i],iOther.m_values[i]);
00242 }
00243 }
00244 private:
00245
00246 void changeSize(unsigned int iToSize) {
00247 assert(m_size<=iToSize);
00248 const size_t memoryNeededInBytes = soahelper::SoATupleHelper<sizeof...(Args),Args...>::spaceNeededFor(iToSize);
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 const std::size_t max_alignment = soahelper::SoATupleHelper<sizeof...(Args),Args...>::max_alignment;
00259 typedef std::aligned_storage<soahelper::SoATupleHelper<sizeof...(Args),Args...>::max_alignment,
00260 soahelper::SoATupleHelper<sizeof...(Args),Args...>::max_alignment> AlignedType;
00261
00262 const size_t itemsNeeded = (memoryNeededInBytes+max_alignment-1)/sizeof(AlignedType);
00263 char * newMemory = static_cast<char*>(static_cast<void*>(new AlignedType[itemsNeeded]));
00264 void * oldMemory =m_values[0];
00265 soahelper::SoATupleHelper<sizeof...(Args),Args...>::moveToNew(newMemory,m_size, iToSize, m_values);
00266 m_reserved = iToSize;
00267 delete [] static_cast<AlignedType*>(oldMemory);
00268 }
00269
00270
00271
00272 void* m_values[sizeof...(Args)];
00273 size_t m_size;
00274 size_t m_reserved;
00275 };
00276 }
00277
00278
00279 #endif