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 #include <utility>
91 
92 // user include files
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>
106 
107  template <typename... Args>
108  class SoATuple {
109  public:
110  typedef typename std::tuple<Args...> element;
111 
113  for (auto& v : m_values) {
114  v = nullptr;
115  }
116  }
117  SoATuple(const SoATuple<Args...>& iOther) : m_size(0), m_reserved(0) {
118  for (auto& v : m_values) {
119  v = nullptr;
120  }
121  reserve(iOther.m_size);
122  soahelper::SoATupleHelper<sizeof...(Args), Args...>::copyToNew(
123  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  SoATuple<Args...> temp(std::move(iRHS));
142  this->swap(temp);
143  return *this;
144  }
145 
147  soahelper::SoATupleHelper<sizeof...(Args), Args...>::destroy(m_values, m_size);
148  typedef std::aligned_storage<soahelper::SoATupleHelper<sizeof...(Args), Args...>::max_alignment,
149  soahelper::SoATupleHelper<sizeof...(Args), Args...>::max_alignment>
150  AlignedType;
151 
152  delete[] static_cast<AlignedType*>(m_values[0]);
153  }
154 
155  // ---------- const member functions ---------------------
156  size_t size() const { return m_size; }
157  size_t capacity() const { return m_reserved; }
158 
160  template <unsigned int I>
161  typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type const& get(
162  unsigned int iIndex) const {
163  typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type
164  ReturnType;
165  return *(static_cast<ReturnType const*>(m_values[I]) + iIndex);
166  }
167 
169  template <unsigned int I>
170  typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type const* begin()
171  const {
172  typedef soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type> Helper;
173  typedef typename Helper::Type ReturnType;
174 #if GCC_PREREQUISITE(4, 7, 0)
175  return static_cast<ReturnType const*>(__builtin_assume_aligned(m_values[I], Helper::kAlignment));
176 #else
177  return static_cast<ReturnType const*>(m_values[I]);
178 #endif
179  }
181  template <unsigned int I>
182  typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type const* end()
183  const {
184  typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type
185  ReturnType;
186  return static_cast<ReturnType const*>(m_values[I]) + m_size;
187  }
188 
189  // ---------- member functions ---------------------------
191  void reserve(unsigned int iToSize) {
192  if (iToSize > m_reserved) {
193  changeSize(iToSize);
194  }
195  }
196 
198  void shrink_to_fit() {
199  if (m_reserved > m_size) {
201  }
202  }
203 
205  void push_back(element const& values) {
206  if (size() + 1 > capacity()) {
207  reserve(size() * 2 + 1);
208  }
209  soahelper::SoATupleHelper<sizeof...(Args), Args...>::push_back(m_values, m_size, values);
210  ++m_size;
211  }
212 
214  template <typename... FArgs>
215  void emplace_back(FArgs&&... values) {
216  if (size() + 1 > capacity()) {
217  reserve(size() * 2 + 1);
218  }
219  soahelper::SoATupleHelper<sizeof...(Args), Args...>::emplace_back(
220  m_values, m_size, std::forward<FArgs>(values)...);
221  ++m_size;
222  }
223 
225  template <unsigned int I>
226  typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type& get(
227  unsigned int iIndex) {
228  typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type
229  ReturnType;
230  return *(static_cast<ReturnType*>(m_values[I]) + iIndex);
231  }
232 
234  template <unsigned int I>
235  typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type* begin() {
236  typedef soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type> Helper;
237  typedef typename Helper::Type ReturnType;
238 #if GCC_PREREQUISITE(4, 7, 0)
239  return static_cast<ReturnType*>(__builtin_assume_aligned(m_values[I], Helper::kAlignment));
240 #else
241  return static_cast<ReturnType*>(m_values[I]);
242 #endif
243  }
245  template <unsigned int I>
246  typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type* end() {
247  typedef typename soahelper::AlignmentHelper<typename std::tuple_element<I, std::tuple<Args...>>::type>::Type
248  ReturnType;
249  return static_cast<ReturnType*>(m_values[I]) + m_size;
250  }
251 
252  void swap(SoATuple<Args...>& iOther) {
253  std::swap(m_size, iOther.m_size);
255  for (unsigned int i = 0; i < sizeof...(Args); ++i) {
256  std::swap(m_values[i], iOther.m_values[i]);
257  }
258  }
259 
260  private:
261  void changeSize(unsigned int iToSize) {
262  assert(m_size <= iToSize);
263  const size_t memoryNeededInBytes = soahelper::SoATupleHelper<sizeof...(Args), Args...>::spaceNeededFor(iToSize);
264  //align memory of the array to be on the strictest alignment boundary for any type in the Tuple
265  // This is done by creating an array of a type that has that same alignment restriction and minimum size.
266  // This has the draw back of possibly padding the array by one extra element if the memoryNeededInBytes is not
267  // a strict multiple of max_alignment.
268  // NOTE: using new char[...] would likely cause more padding based on C++11 5.3.4 paragraph 10 where it
269  // says the alignment will be for the strictest requirement for an object whose size < size of array. So
270  // if the array were for 64 bytes and the strictest requirement of any object was 8 bytes then the entire
271  // char array would be aligned on an 8 byte boundary. However, if the SoATuple<char,char> only 1 byte alignment
272  // is needed. The following algorithm would require only 1 byte alignment
273  const std::size_t max_alignment = soahelper::SoATupleHelper<sizeof...(Args), Args...>::max_alignment;
274  typedef std::aligned_storage<soahelper::SoATupleHelper<sizeof...(Args), Args...>::max_alignment,
275  soahelper::SoATupleHelper<sizeof...(Args), Args...>::max_alignment>
276  AlignedType;
277  //If needed, pad the number of items by 1
278  const size_t itemsNeeded = (memoryNeededInBytes + max_alignment - 1) / sizeof(AlignedType);
279  char* newMemory = static_cast<char*>(static_cast<void*>(new AlignedType[itemsNeeded]));
280  void* oldMemory = m_values[0];
281  soahelper::SoATupleHelper<sizeof...(Args), Args...>::moveToNew(newMemory, m_size, iToSize, m_values);
282  m_reserved = iToSize;
283  delete[] static_cast<AlignedType*>(oldMemory);
284  }
285  // ---------- member data --------------------------------
286  //Pointers to where each column starts in the shared memory array
287  //m_values[0] also points to the beginning of the shared memory area
288  void* m_values[sizeof...(Args)];
289  size_t m_size;
290  size_t m_reserved;
291  };
292 } // namespace edm
293 
294 #endif
void swap(SoATuple< Args... > &iOther)
Definition: SoATuple.h:252
void changeSize(unsigned int iToSize)
Definition: SoATuple.h:261
std::tuple< Args... > element
Definition: SoATuple.h:110
size_t m_reserved
Definition: SoATuple.h:290
size_t m_size
Definition: SoATuple.h:289
assert(be >=bs)
void swap(Association< C > &lhs, Association< C > &rhs)
Definition: Association.h:112
SoATuple(SoATuple< Args... > &&iOther)
Definition: SoATuple.h:127
void push_back(element const &values)
Definition: SoATuple.h:205
std::map< DetId, double > ReturnType
size_t capacity() const
Definition: SoATuple.h:157
soahelper::AlignmentHelper< typename std::tuple_element< I, std::tuple< Args... > >::type >::Type const * begin() const
Definition: SoATuple.h:170
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:235
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:182
void emplace_back(FArgs &&... values)
Definition: SoATuple.h:215
HLT enums.
soahelper::AlignmentHelper< typename std::tuple_element< I, std::tuple< Args... > >::type >::Type * end()
Definition: SoATuple.h:246
void shrink_to_fit()
Definition: SoATuple.h:198
size_t size() const
Definition: SoATuple.h:156
SoATuple< Args... > & operator=(SoATuple< Args... > &&iRHS)
Definition: SoATuple.h:140
def move(src, dest)
Definition: eostools.py:511
void reserve(unsigned int iToSize)
Definition: SoATuple.h:191
SoATuple(const SoATuple< Args... > &iOther)
Definition: SoATuple.h:117
void * m_values[sizeof...(Args)]
Definition: SoATuple.h:288