CMS 3D CMS Logo

SoATuple.h
Go to the documentation of this file.
1 #ifndef FWCore_Utilities_SoATuple_h
2 #define FWCore_Utilities_SoATuple_h
3 // -*- C++ -*-
4 //
5 // Package: FWCore/Utilities
6 // Class : SoATuple
7 //
81 //
82 // Original Author: Chris Jones
83 // Created: Tue, 16 Apr 2013 20:34:31 GMT
84 //
85 
86 // system include files
87 #include <algorithm>
88 #include <tuple>
89 #include <cassert>
90 
91 // user include files
94 
95 
96 // forward declarations
97 
98 namespace edm {
99 
100  //The class Aligned is used to specify a non-default alignment for a class
102 
103  //Proper alignment for doing vectorized operations on CPU
104  template<typename T> using AlignedVec = Aligned<T,16>;
105 
106  template <typename... Args>
107  class SoATuple
108  {
109 
110  public:
111  typedef typename std::tuple<Args...> element;
112 
114  for(auto& v : m_values) {
115  v = nullptr;
116  }
117  }
119  for(auto& v : m_values) {
120  v = nullptr;
121  }
122  reserve(iOther.m_size);
123  soahelper::SoATupleHelper<sizeof...(Args),Args...>::copyToNew(static_cast<char*>(m_values[0]),iOther.m_size,m_reserved,iOther.m_values,m_values);
124  m_size = iOther.m_size;
125  }
126 
128  for(auto& v : m_values) {
129  v = nullptr;
130  }
131  this->swap(iOther);
132  }
133 
134  const SoATuple<Args...>& operator=(const SoATuple<Args...>& iRHS) {
135  SoATuple<Args...> temp(iRHS);
136  this->swap(temp);
137  return *this;
138  }
139 
141  soahelper::SoATupleHelper<sizeof...(Args),Args...>::destroy(m_values,m_size);
142  typedef std::aligned_storage<soahelper::SoATupleHelper<sizeof...(Args),Args...>::max_alignment,
143  soahelper::SoATupleHelper<sizeof...(Args),Args...>::max_alignment> AlignedType;
144 
145  delete [] static_cast<AlignedType*>(m_values[0]);
146  }
147 
148  // ---------- const member functions ---------------------
149  size_t size() const { return m_size;}
150  size_t capacity() const {return m_reserved;}
151 
153  template<unsigned int I>
154  typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type const& get(unsigned int iIndex) const {
155  typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type ReturnType;
156  return *(static_cast<ReturnType const*>(m_values[I])+iIndex);
157  }
158 
160  template<unsigned int I>
161  typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type const* begin() const {
162  typedef soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type> Helper;
163  typedef typename Helper::Type ReturnType;
164 #if GCC_PREREQUISITE(4,7,0)
165  return static_cast<ReturnType const*>(__builtin_assume_aligned(m_values[I],Helper::kAlignment));
166 #else
167  return static_cast<ReturnType const*>(m_values[I]);
168 #endif
169  }
171  template<unsigned int I>
172  typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type const* end() const {
173  typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type ReturnType;
174  return static_cast<ReturnType const*>(m_values[I])+m_size;
175  }
176 
177  // ---------- member functions ---------------------------
179  void reserve(unsigned int iToSize) {
180  if(iToSize > m_reserved) {
181  changeSize(iToSize);
182  }
183  }
184 
186  void shrink_to_fit() {
187  if(m_reserved > m_size) {
189  }
190  }
191 
193  void push_back(element const& values) {
194  if(size()+1>capacity()) {
195  reserve(size()*2+1);
196  }
197  soahelper::SoATupleHelper<sizeof...(Args),Args...>::push_back(m_values,m_size,values);
198  ++m_size;
199  }
200 
202  template< typename... FArgs>
203  void emplace_back(FArgs&&... values) {
204  if(size()+1>capacity()) {
205  reserve(size()*2+1);
206  }
207  soahelper::SoATupleHelper<sizeof...(Args),Args...>::emplace_back(m_values,m_size,std::forward<FArgs>(values)...);
208  ++m_size;
209  }
210 
212  template<unsigned int I>
213  typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type& get(unsigned int iIndex) {
214  typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type ReturnType;
215  return *(static_cast<ReturnType*>(m_values[I])+iIndex);
216  }
217 
219  template<unsigned int I>
220  typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type* begin() {
221  typedef soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type> Helper;
222  typedef typename Helper::Type ReturnType;
223 #if GCC_PREREQUISITE(4,7,0)
224  return static_cast<ReturnType*>(__builtin_assume_aligned(m_values[I],Helper::kAlignment));
225 #else
226  return static_cast<ReturnType*>(m_values[I]);
227 #endif
228  }
230  template<unsigned int I>
231  typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type* end() {
232  typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type ReturnType;
233  return static_cast<ReturnType*>(m_values[I])+m_size;
234  }
235 
236  void swap(SoATuple<Args...>& iOther) {
237  std::swap(m_size,iOther.m_size);
239  for(unsigned int i=0; i<sizeof...(Args);++i) {
240  std::swap(m_values[i],iOther.m_values[i]);
241  }
242  }
243  private:
244 
245  void changeSize(unsigned int iToSize) {
246  assert(m_size<=iToSize);
247  const size_t memoryNeededInBytes = soahelper::SoATupleHelper<sizeof...(Args),Args...>::spaceNeededFor(iToSize);
248  //align memory of the array to be on the strictest alignment boundary for any type in the Tuple
249  // This is done by creating an array of a type that has that same alignment restriction and minimum size.
250  // This has the draw back of possibly padding the array by one extra element if the memoryNeededInBytes is not
251  // a strict multiple of max_alignment.
252  // NOTE: using new char[...] would likely cause more padding based on C++11 5.3.4 paragraph 10 where it
253  // says the alignment will be for the strictest requirement for an object whose size < size of array. So
254  // if the array were for 64 bytes and the strictest requirement of any object was 8 bytes then the entire
255  // char array would be aligned on an 8 byte boundary. However, if the SoATuple<char,char> only 1 byte alignment
256  // is needed. The following algorithm would require only 1 byte alignment
257  const std::size_t max_alignment = soahelper::SoATupleHelper<sizeof...(Args),Args...>::max_alignment;
258  typedef std::aligned_storage<soahelper::SoATupleHelper<sizeof...(Args),Args...>::max_alignment,
259  soahelper::SoATupleHelper<sizeof...(Args),Args...>::max_alignment> AlignedType;
260  //If needed, pad the number of items by 1
261  const size_t itemsNeeded = (memoryNeededInBytes+max_alignment-1)/sizeof(AlignedType);
262  char * newMemory = static_cast<char*>(static_cast<void*>(new AlignedType[itemsNeeded]));
263  void * oldMemory =m_values[0];
264  soahelper::SoATupleHelper<sizeof...(Args),Args...>::moveToNew(newMemory,m_size, iToSize, m_values);
265  m_reserved = iToSize;
266  delete [] static_cast<AlignedType*>(oldMemory);
267  }
268  // ---------- member data --------------------------------
269  //Pointers to where each column starts in the shared memory array
270  //m_values[0] also points to the beginning of the shared memory area
271  void* m_values[sizeof...(Args)];
272  size_t m_size;
273  size_t m_reserved;
274  };
275 }
276 
277 
278 #endif
type
Definition: HCALResponse.h:21
soahelper::AlignmentHelper< typename std::tuple_element< I, std::tuple< Args... > >::type >::Type const * begin() const
Definition: SoATuple.h:161
void swap(SoATuple< Args... > &iOther)
Definition: SoATuple.h:236
void changeSize(unsigned int iToSize)
Definition: SoATuple.h:245
std::tuple< Args... > element
Definition: SoATuple.h:111
def destroy(e)
Definition: pyrootRender.py:13
size_t m_reserved
Definition: SoATuple.h:273
size_t m_size
Definition: SoATuple.h:272
void emplace_back(FArgs &&...values)
Definition: SoATuple.h:203
SoATuple(SoATuple< Args... > &&iOther)
Definition: SoATuple.h:127
void push_back(element const &values)
Definition: SoATuple.h:193
std::map< DetId, double > ReturnType
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
size_t size() const
Definition: SoATuple.h:149
const std::complex< double > I
Definition: I.h:8
soahelper::AlignmentHelper< typename std::tuple_element< I, std::tuple< Args... > >::type >::Type * begin()
Definition: SoATuple.h:220
size_t capacity() const
Definition: SoATuple.h:150
const SoATuple< Args... > & operator=(const SoATuple< Args... > &iRHS)
Definition: SoATuple.h:134
soahelper::AlignmentHelper< typename std::tuple_element< I, std::tuple< Args... > >::type >::Type const * end() const
Definition: SoATuple.h:172
HLT enums.
soahelper::AlignmentHelper< typename std::tuple_element< I, std::tuple< Args... > >::type >::Type * end()
Definition: SoATuple.h:231
void shrink_to_fit()
Definition: SoATuple.h:186
void reserve(unsigned int iToSize)
Definition: SoATuple.h:179
SoATuple(const SoATuple< Args... > &iOther)
Definition: SoATuple.h:118
void * m_values[sizeof...(Args)]
Definition: SoATuple.h:271