CMS 3D CMS Logo

SoATupleHelper.h
Go to the documentation of this file.
1 #ifndef FWCore_Utilities_SoATupleHelper_h
2 #define FWCore_Utilities_SoATupleHelper_h
3 // -*- C++ -*-
4 //
5 // Package: Package
6 // Class : SoATupleHelper
7 //
16 //
17 // Original Author: Chris Jones
18 // Created: Tue, 16 Apr 2013 21:06:08 GMT
19 //
20 
21 // system include files
22 #include <tuple>
23 #include <algorithm>
24 
25 // user include files
26 
27 // forward declarations
28 namespace edm {
29  namespace soahelper {
30 
33  constexpr unsigned int padding_needed(size_t iSizeSoFar, unsigned int iBoundary) {
34  return (iBoundary - iSizeSoFar % iBoundary) % iBoundary;
35  }
36 
42  template <unsigned int I, unsigned int J, typename Ret, typename... Args>
43  struct arg_puller;
44 
46  template <unsigned int I, unsigned int J, typename Ret, typename F, typename... Args>
47  struct arg_puller<I, J, Ret, F, Args...> {
48  static Ret pull(F const&, const Args&... args) { return arg_puller<I + 1, J, Ret, Args...>::pull(args...); }
49  };
50 
52  template <unsigned int I, typename Ret, typename F, typename... Args>
53  struct arg_puller<I, I, Ret, F, Args...> {
54  static Ret pull(F const& iV, const Args&...) { return iV; }
55  };
56 
61  template <typename T, unsigned int ALIGNMENT>
62  struct Aligned {
63  static const unsigned int kAlignment = ALIGNMENT;
64  typedef T Type;
65  };
66 
71  template <typename T>
72  struct AlignmentHelper {
73  static const std::size_t kAlignment = alignof(T);
74  typedef T Type;
75  };
76 
80  template <typename T, unsigned int ALIGNMENT>
81  struct AlignmentHelper<Aligned<T, ALIGNMENT>> {
82  static const std::size_t kAlignment = ALIGNMENT;
83  typedef T Type;
84  };
85 
90  template <unsigned int I, typename... Args>
91  struct SoATupleHelper {
92  typedef AlignmentHelper<typename std::tuple_element<I - 1, std::tuple<Args...>>::type> AlignmentInfo;
93  typedef typename AlignmentInfo::Type Type;
94  typedef SoATupleHelper<I - 1, Args...> NextHelper;
95 
96  static const std::size_t max_alignment =
97  AlignmentInfo::kAlignment > NextHelper::max_alignment ? AlignmentInfo::kAlignment : NextHelper::max_alignment;
98 
99  // ---------- static member functions --------------------
100  static size_t moveToNew(char* iNewMemory, size_t iSize, size_t iReserve, void** oToSet);
101  static size_t copyToNew(char* iNewMemory, size_t iSize, size_t iReserve, void* const* iFrom, void** oToSet);
102  static size_t spaceNeededFor(unsigned int iNElements);
103  static void push_back(void** iToSet, size_t iSize, std::tuple<Args...> const& iValues);
104  template <typename... FArgs>
105  static void emplace_back(void** iToSet, size_t iSize, FArgs... iValues);
106  static void destroy(void** iToSet, size_t iSize);
107 
108  // ---------- member functions ---------------------------
109  SoATupleHelper(const SoATupleHelper&) = delete; // stop default
110 
111  const SoATupleHelper& operator=(const SoATupleHelper&) = delete; // stop default
112  };
113 
114  //Specialization used to stop recursion
115  template <typename... Args>
116  struct SoATupleHelper<0, Args...> {
117  static const std::size_t max_alignment = 0;
118  static void destroy(void** /*iToSet*/, size_t /*iSize*/) {}
119 
120  static void push_back(void** /*iToSet*/, size_t /*iSize*/, std::tuple<Args...> const& /*values*/) {}
121 
122  template <typename... FArgs>
123  static void emplace_back(void** iToSet, size_t iSize, FArgs... iValues) {}
124 
125  static size_t spaceNeededFor(unsigned int /*iNElements*/) { return 0; }
126 
127  static size_t moveToNew(char* /*iNewMemory*/, size_t /*iSize*/, size_t /*iReserve*/, void** /*oToSet*/) {
128  return 0;
129  }
130 
131  static size_t copyToNew(
132  char* /*iNewMemory*/, size_t /*iSize*/, size_t /*iReserve*/, void* const* /*iFrom*/, void** /*oToSet*/) {
133  return 0;
134  }
135  };
136 
137  template <unsigned int I, typename... Args>
138  size_t SoATupleHelper<I, Args...>::moveToNew(char* iNewMemory, size_t iSize, size_t iReserve, void** oToSet) {
139  size_t usedSoFar = NextHelper::moveToNew(iNewMemory, iSize, iReserve, oToSet);
140 
141  //find new start
142  const unsigned int boundary = AlignmentInfo::kAlignment;
143 
144  Type* newStart = reinterpret_cast<Type*>(iNewMemory + usedSoFar + padding_needed(usedSoFar, boundary));
145 
146  void** oldStart = oToSet + I - 1;
147 
148  Type* oldValues = static_cast<Type*>(*oldStart);
149  if (oldValues != nullptr) {
150  auto ptr = newStart;
151  for (auto it = oldValues; it != oldValues + iSize; ++it, ++ptr) {
152  new (ptr) Type(std::move(*it));
153  }
154  for (auto it = oldValues; it != oldValues + iSize; ++it) {
155  it->~Type();
156  }
157  }
158  *oldStart = newStart;
159  unsigned int additionalSize = padding_needed(usedSoFar, boundary) + iReserve * sizeof(Type);
160  return usedSoFar + additionalSize;
161  }
162 
163  template <unsigned int I, typename... Args>
165  char* iNewMemory, size_t iSize, size_t iReserve, void* const* iFrom, void** oToSet) {
166  size_t usedSoFar = NextHelper::copyToNew(iNewMemory, iSize, iReserve, iFrom, oToSet);
167 
168  //find new start
169  const unsigned int boundary = AlignmentInfo::kAlignment;
170 
171  Type* newStart = reinterpret_cast<Type*>(iNewMemory + usedSoFar + padding_needed(usedSoFar, boundary));
172 
173  void* const* oldStart = iFrom + I - 1;
174 
175  Type* oldValues = static_cast<Type*>(*oldStart);
176  if (oldValues != nullptr) {
177  auto ptr = newStart;
178  for (auto it = oldValues; it != oldValues + iSize; ++it, ++ptr) {
179  new (ptr) Type(*it);
180  }
181  }
182  *(oToSet + I - 1) = newStart;
183  unsigned int additionalSize = padding_needed(usedSoFar, boundary) + iReserve * sizeof(Type);
184  return usedSoFar + additionalSize;
185  }
186 
187  template <unsigned int I, typename... Args>
188  size_t SoATupleHelper<I, Args...>::spaceNeededFor(unsigned int iNElements) {
189  size_t usedSoFar = NextHelper::spaceNeededFor(iNElements);
190  const unsigned int boundary = AlignmentInfo::kAlignment;
191  unsigned int additionalSize = padding_needed(usedSoFar, boundary) + iNElements * sizeof(Type);
192  return usedSoFar + additionalSize;
193  }
194 
195  template <unsigned int I, typename... Args>
196  void SoATupleHelper<I, Args...>::push_back(void** iToSet, size_t iSize, std::tuple<Args...> const& iValues) {
197  new (static_cast<Type*>(*(iToSet + I - 1)) + iSize) Type(std::get<I - 1>(iValues));
198 
199  NextHelper::push_back(iToSet, iSize, iValues);
200  }
201 
202  template <unsigned int I, typename... Args>
203  template <typename... FArgs>
204  void SoATupleHelper<I, Args...>::emplace_back(void** iToSet, size_t iSize, FArgs... iValues) {
205  new (static_cast<Type*>(*(iToSet + I - 1)) + iSize)
206  Type(arg_puller<0, I - 1, Type const&, FArgs...>::pull(std::forward<FArgs>(iValues)...));
207 
208  NextHelper::emplace_back(iToSet, iSize, std::forward<FArgs>(iValues)...);
209  }
210 
211  template <unsigned int I, typename... Args>
212  void SoATupleHelper<I, Args...>::destroy(void** iToSet, size_t iSize) {
213  void** start = iToSet + I - 1;
214  Type* values = static_cast<Type*>(*start);
215 
216  for (auto it = values; it != values + iSize; ++it) {
217  it->~Type();
218  }
219 
220  NextHelper::destroy(iToSet, iSize);
221  }
222 
223  } // namespace soahelper
224 } // namespace edm
225 
226 #endif
Definition: start.py:1
static size_t moveToNew(char *iNewMemory, size_t iSize, size_t iReserve, void **oToSet)
type
Definition: HCALResponse.h:21
static size_t moveToNew(char *, size_t, size_t, void **)
def destroy(e)
Definition: pyrootRender.py:15
AlignmentHelper< typename std::tuple_element< I-1, std::tuple< Args... > >::type > AlignmentInfo
static size_t copyToNew(char *, size_t, size_t, void *const *, void **)
static void emplace_back(void **iToSet, size_t iSize, FArgs...iValues)
static void push_back(void **iToSet, size_t iSize, std::tuple< Args... > const &iValues)
static size_t copyToNew(char *iNewMemory, size_t iSize, size_t iReserve, void *const *iFrom, void **oToSet)
static Ret pull(F const &, const Args &...args)
const std::complex< double > I
Definition: I.h:8
SoATupleHelper< I-1, Args... > NextHelper
HLT enums.
static void push_back(void **, size_t, std::tuple< Args... > const &)
static void emplace_back(void **iToSet, size_t iSize, FArgs...iValues)
static Ret pull(F const &iV, const Args &...)
static uInt32 F(BLOWFISH_CTX *ctx, uInt32 x)
Definition: blowfish.cc:281
static size_t spaceNeededFor(unsigned int iNElements)
long double T
static size_t spaceNeededFor(unsigned int)
def move(src, dest)
Definition: eostools.py:511
constexpr unsigned int padding_needed(size_t iSizeSoFar, unsigned int iBoundary)
#define constexpr
static void destroy(void **iToSet, size_t iSize)