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 // forward declarations
96 
97 namespace edm {
98 
99  //The class Aligned is used to specify a non-default alignment for a class
101 
102  //Proper alignment for doing vectorized operations on CPU
103  template <typename T>
105 
106  template <typename... Args>
107  class SoATuple {
108  public:
109  typedef typename std::tuple<Args...> element;
110 
112  for (auto& v : m_values) {
113  v = nullptr;
114  }
115  }
116  SoATuple(const SoATuple<Args...>& iOther) : m_size(0), m_reserved(0) {
117  for (auto& v : m_values) {
118  v = nullptr;
119  }
120  reserve(iOther.m_size);
121  soahelper::SoATupleHelper<sizeof...(Args), Args...>::copyToNew(
122  static_cast<char*>(m_values[0]), iOther.m_size, m_reserved, iOther.m_values, m_values);
123  m_size = iOther.m_size;
124  }
125 
127  for (auto& v : m_values) {
128  v = nullptr;
129  }
130  this->swap(iOther);
131  }
132 
133  const SoATuple<Args...>& operator=(const SoATuple<Args...>& iRHS) {
134  SoATuple<Args...> temp(iRHS);
135  this->swap(temp);
136  return *this;
137  }
138 
140  soahelper::SoATupleHelper<sizeof...(Args), Args...>::destroy(m_values, m_size);
141  typedef std::aligned_storage<soahelper::SoATupleHelper<sizeof...(Args), Args...>::max_alignment,
142  soahelper::SoATupleHelper<sizeof...(Args), Args...>::max_alignment>
143  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(
155  unsigned int iIndex) const {
156  typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type
157  ReturnType;
158  return *(static_cast<ReturnType const*>(m_values[I]) + iIndex);
159  }
160 
162  template <unsigned int I>
163  typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type const* begin()
164  const {
165  typedef soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type> Helper;
166  typedef typename Helper::Type ReturnType;
167 #if GCC_PREREQUISITE(4, 7, 0)
168  return static_cast<ReturnType const*>(__builtin_assume_aligned(m_values[I], Helper::kAlignment));
169 #else
170  return static_cast<ReturnType const*>(m_values[I]);
171 #endif
172  }
174  template <unsigned int I>
175  typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type const* end()
176  const {
177  typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type
178  ReturnType;
179  return static_cast<ReturnType const*>(m_values[I]) + m_size;
180  }
181 
182  // ---------- member functions ---------------------------
184  void reserve(unsigned int iToSize) {
185  if (iToSize > m_reserved) {
186  changeSize(iToSize);
187  }
188  }
189 
191  void shrink_to_fit() {
192  if (m_reserved > m_size) {
194  }
195  }
196 
198  void push_back(element const& values) {
199  if (size() + 1 > capacity()) {
200  reserve(size() * 2 + 1);
201  }
202  soahelper::SoATupleHelper<sizeof...(Args), Args...>::push_back(m_values, m_size, values);
203  ++m_size;
204  }
205 
207  template <typename... FArgs>
208  void emplace_back(FArgs&&... values) {
209  if (size() + 1 > capacity()) {
210  reserve(size() * 2 + 1);
211  }
212  soahelper::SoATupleHelper<sizeof...(Args), Args...>::emplace_back(
213  m_values, m_size, std::forward<FArgs>(values)...);
214  ++m_size;
215  }
216 
218  template <unsigned int I>
219  typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type& get(
220  unsigned int iIndex) {
221  typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type
222  ReturnType;
223  return *(static_cast<ReturnType*>(m_values[I]) + iIndex);
224  }
225 
227  template <unsigned int I>
228  typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type* begin() {
229  typedef soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type> Helper;
230  typedef typename Helper::Type ReturnType;
231 #if GCC_PREREQUISITE(4, 7, 0)
232  return static_cast<ReturnType*>(__builtin_assume_aligned(m_values[I], Helper::kAlignment));
233 #else
234  return static_cast<ReturnType*>(m_values[I]);
235 #endif
236  }
238  template <unsigned int I>
239  typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type* end() {
240  typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type
241  ReturnType;
242  return static_cast<ReturnType*>(m_values[I]) + m_size;
243  }
244 
245  void swap(SoATuple<Args...>& iOther) {
246  std::swap(m_size, iOther.m_size);
248  for (unsigned int i = 0; i < sizeof...(Args); ++i) {
249  std::swap(m_values[i], iOther.m_values[i]);
250  }
251  }
252 
253  private:
254  void changeSize(unsigned int iToSize) {
255  assert(m_size <= iToSize);
256  const size_t memoryNeededInBytes = soahelper::SoATupleHelper<sizeof...(Args), Args...>::spaceNeededFor(iToSize);
257  //align memory of the array to be on the strictest alignment boundary for any type in the Tuple
258  // This is done by creating an array of a type that has that same alignment restriction and minimum size.
259  // This has the draw back of possibly padding the array by one extra element if the memoryNeededInBytes is not
260  // a strict multiple of max_alignment.
261  // NOTE: using new char[...] would likely cause more padding based on C++11 5.3.4 paragraph 10 where it
262  // says the alignment will be for the strictest requirement for an object whose size < size of array. So
263  // if the array were for 64 bytes and the strictest requirement of any object was 8 bytes then the entire
264  // char array would be aligned on an 8 byte boundary. However, if the SoATuple<char,char> only 1 byte alignment
265  // is needed. The following algorithm would require only 1 byte alignment
266  const std::size_t max_alignment = soahelper::SoATupleHelper<sizeof...(Args), Args...>::max_alignment;
267  typedef std::aligned_storage<soahelper::SoATupleHelper<sizeof...(Args), Args...>::max_alignment,
268  soahelper::SoATupleHelper<sizeof...(Args), Args...>::max_alignment>
269  AlignedType;
270  //If needed, pad the number of items by 1
271  const size_t itemsNeeded = (memoryNeededInBytes + max_alignment - 1) / sizeof(AlignedType);
272  char* newMemory = static_cast<char*>(static_cast<void*>(new AlignedType[itemsNeeded]));
273  void* oldMemory = m_values[0];
274  soahelper::SoATupleHelper<sizeof...(Args), Args...>::moveToNew(newMemory, m_size, iToSize, m_values);
275  m_reserved = iToSize;
276  delete[] static_cast<AlignedType*>(oldMemory);
277  }
278  // ---------- member data --------------------------------
279  //Pointers to where each column starts in the shared memory array
280  //m_values[0] also points to the beginning of the shared memory area
281  void* m_values[sizeof...(Args)];
282  size_t m_size;
283  size_t m_reserved;
284  };
285 } // namespace edm
286 
287 #endif
type
Definition: HCALResponse.h:21
soahelper::AlignmentHelper< typename std::tuple_element< I, std::tuple< Args... > >::type >::Type const * begin() const
Definition: SoATuple.h:163
void swap(SoATuple< Args... > &iOther)
Definition: SoATuple.h:245
void changeSize(unsigned int iToSize)
Definition: SoATuple.h:254
std::tuple< Args... > element
Definition: SoATuple.h:109
def destroy(e)
Definition: pyrootRender.py:15
size_t m_reserved
Definition: SoATuple.h:283
size_t m_size
Definition: SoATuple.h:282
void emplace_back(FArgs &&...values)
Definition: SoATuple.h:208
SoATuple(SoATuple< Args... > &&iOther)
Definition: SoATuple.h:126
void push_back(element const &values)
Definition: SoATuple.h:198
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:228
size_t capacity() const
Definition: SoATuple.h:150
const SoATuple< Args... > & operator=(const SoATuple< Args... > &iRHS)
Definition: SoATuple.h:133
soahelper::AlignmentHelper< typename std::tuple_element< I, std::tuple< Args... > >::type >::Type const * end() const
Definition: SoATuple.h:175
HLT enums.
soahelper::AlignmentHelper< typename std::tuple_element< I, std::tuple< Args... > >::type >::Type * end()
Definition: SoATuple.h:239
void shrink_to_fit()
Definition: SoATuple.h:191
void reserve(unsigned int iToSize)
Definition: SoATuple.h:184
SoATuple(const SoATuple< Args... > &iOther)
Definition: SoATuple.h:116
void * m_values[sizeof...(Args)]
Definition: SoATuple.h:281