ATLAS Offline Software
AuxTypeVectorFactory.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 /**
5  * @file AthContainers/tools/AuxTypeVectorFactory.icc
6  * @author scott snyder <snyder@bnl.gov>
7  * @date May, 2014
8  * @brief Factory objects that creates vectors using @c AuxTypeVector.
9  */
10 
11 
12 #ifndef XAOD_STANDALONE
13 #include "AthLinks/ElementLink.h"
14 #endif
15 
16 
17 namespace SG {
18 
19 
20 #ifndef XAOD_STANDALONE
21 /**
22  * @brief Apply output thinning to one item.
23  *
24  * Generic version; doesn't do anything.
25  */
26 template <class T>
27 inline
28 void applyAuxThinning (const SG::ThinningCache*, T*)
29 {
30 }
31 
32 
33 /**
34  * @brief Apply output thinning to an ElementLink.
35  * @param p Object being written.
36  * @param tc Thinning cache for the current stream.
37  */
38 template <class T>
39 inline
40 void applyAuxThinning (const SG::ThinningCache* tc, ElementLink<T>* p)
41 {
42  p->thin (tc);
43 }
44 
45 
46 /**
47  * @brief Apply output thinning to a vector of ElementLinks.
48  * @param p Object being written.
49  * @param tc Thinning cache for the current stream.
50  */
51 template <class T>
52 void applyAuxThinning (const SG::ThinningCache* tc, std::vector<ElementLink<T> >* p)
53 {
54  for (ElementLink<T>& el : *p) {
55  el.thin (tc);
56  }
57 }
58 #endif
59 
60 
61 /**
62  * @brief Create a vector object of this type.
63  * @param auxid ID for the variable being created.
64  * @param size Initial size of the new vector.
65  * @param capacity Initial capacity of the new vector.
66  * @param isLinked True if this variable is linked from another one.
67  */
68 template <class T, class ALLOC>
69 std::unique_ptr<IAuxTypeVector>
70 AuxTypeVectorFactoryImpl<T, ALLOC>::create (SG::auxid_t auxid,
71  size_t size, size_t capacity,
72  bool isLinked) const
73 {
74  return std::make_unique<AuxTypeVector<T, ALLOC> > (auxid, size, capacity,
75  isLinked);
76 }
77 
78 
79 /**
80  * @brief Create a vector object of this type from a data blob.
81  * @param auxid ID for the variable being created.
82  * @param data The vector object.
83  * @param isPacked If true, @c data is a @c PackedContainer.
84  * @param ownFlag If true, the newly-created IAuxTypeVector object
85  * will take ownership of @c data.
86  * @param isLinked True if this variable is linked from another one.
87  *
88  * This is for types which are packable.
89  */
90 template <class T, class ALLOC>
91 std::unique_ptr<IAuxTypeVector>
92 AuxTypeVectorFactoryImpl<T, ALLOC>::createFromData (auxid_t auxid,
93  void* data,
94  bool isPacked,
95  bool ownFlag,
96  bool isLinked,
97  std::true_type) const
98 {
99  if (isPacked) {
100  using unpacked_vector_type = typename SG::AuxDataTraits<T, ALLOC>::vector_type;
101  using element_type = typename unpacked_vector_type::value_type;
102  using unpacked_vector_allocator_type = typename SG::AuxDataTraits<T, ALLOC>::allocator_type;
103  using vector_type = SG::PackedContainer<element_type, unpacked_vector_allocator_type>;
104  return std::make_unique<AuxTypeVectorHolder<T, vector_type > >
105  (auxid, reinterpret_cast<vector_type*>(data), ownFlag, isLinked);
106  }
107  else {
108  using vector_type = typename SG::AuxDataTraits<T, ALLOC>::vector_type;
109  return std::make_unique<AuxTypeVectorHolder<T, vector_type> > (auxid, reinterpret_cast<vector_type*>(data), true, isLinked);
110  }
111 }
112 
113 
114 /**
115  * @brief Create a vector object of this type from a data blob.
116  * @param auxid ID for the variable being created.
117  * @param data The vector object.
118  * @param isPacked If true, @c data is a @c PackedContainer.
119  * @param ownFlag If true, the newly-created IAuxTypeVector object
120  * will take ownership of @c data.
121  * @param isLinked True if this variable is linked from another one.
122  *
123  * This is for types which are not packable.
124  */
125 template <class T, class ALLOC>
126 std::unique_ptr<IAuxTypeVector>
127 AuxTypeVectorFactoryImpl<T, ALLOC>::createFromData (auxid_t auxid,
128  void* data,
129  bool isPacked,
130  bool ownFlag,
131  bool isLinked,
132  std::false_type) const
133 {
134  if (isPacked) std::abort();
135  using vector_type = typename SG::AuxDataTraits<T, ALLOC>::vector_type;
136  return std::make_unique<AuxTypeVectorHolder<T, vector_type> >
137  (auxid, reinterpret_cast<vector_type*>(data), ownFlag, isLinked);
138 }
139 
140 
141 /**
142  * @brief Create a vector object of this type from a data blob.
143  * @param auxid ID for the variable being created.
144  * @param data The vector object.
145  * @param linkedVector The interface for another variable linked to this one,
146  * or nullptr if there isn't one.
147  * (We do not take ownership.)
148  * @param isPacked If true, @c data is a @c PackedContainer.
149  * @param ownFlag If true, the newly-created IAuxTypeVector object
150  * will take ownership of @c data.
151  * @param isLinked True if this variable is linked from another one.
152  *
153  * If the element type is T, then @c data should be a pointer
154  * to a std::vector<T> object, which was obtained with @c new.
155  * But if @c isPacked is @c true, then @c data
156  * should instead point at an object of type @c SG::PackedContainer<T>.
157  *
158  * Returns a newly-allocated object.
159  */
160 template <class T, class ALLOC>
161 std::unique_ptr<IAuxTypeVector>
162 AuxTypeVectorFactoryImpl<T, ALLOC>::createFromData (SG::auxid_t auxid,
163  void* data,
164  IAuxTypeVector* linkedVector,
165  bool isPacked,
166  bool ownFlag,
167  bool isLinked) const
168 {
169  if (linkedVector) std::abort();
170  return createFromData (auxid,
171  data, isPacked, ownFlag,
172  isLinked,
173  typename DataModel_detail::can_pack<T>::type());
174 }
175 
176 
177 /// Helper for copy; returns a pointer to the first destination object,
178 /// or nullptr if the destination was cleared rather than copied.
179 template <class T, class ALLOC>
180 auto
181 AuxTypeVectorFactoryImpl<T, ALLOC>::copyImpl (SG::auxid_t auxid,
182  AuxVectorData& dst,
183  size_t dst_index,
184  const AuxVectorData& src,
185  size_t src_index,
186  size_t n) const -> vector_value_type*
187 {
188  if (n == 0) return nullptr;
189  auto dstptr = reinterpret_cast<vector_value_type*>(dst.getDataArray (auxid));
190  if (&src == &dst) {
191  // Source and destination containers are the same.
192  // We don't need to bother with fetching the src pointer, but we do
193  // need to check for overlaps.
194  if (dst_index >= src_index && dst_index < src_index+n) {
195  std::copy_backward (dstptr+src_index, dstptr+src_index+n, dstptr+dst_index+n);
196  }
197  else {
198  std::copy (dstptr+src_index, dstptr+src_index+n, dstptr+dst_index);
199  }
200  return dstptr + dst_index;
201  }
202  else {
203  auto srcptr = reinterpret_cast<const vector_value_type*>(src.getDataArrayAllowMissing (auxid));
204  if (srcptr) {
205  std::copy (srcptr+src_index, srcptr+src_index+n, dstptr+dst_index);
206  return dstptr + dst_index;
207  }
208  else {
209  std::fill (dstptr+dst_index, dstptr+dst_index+n, SG::Zero<vector_value_type>::zero());
210  return nullptr;
211  }
212  }
213 }
214 
215 
216 
217 /**
218  * @brief Copy elements between vectors.
219  * @param auxid The aux data item being operated on.
220  * @param dst Container for the destination vector.
221  * @param dst_index Index of the first destination element in the vector.
222  * @param src Container for the source vector.
223  * @param src_index Index of the first source element in the vector.
224  * @param n Number of elements to copy.
225  *
226  * @c dst and @ src can be either the same or different.
227  */
228 template <class T, class ALLOC>
229 void AuxTypeVectorFactoryImpl<T, ALLOC>::copy (SG::auxid_t auxid,
230  AuxVectorData& dst,
231  size_t dst_index,
232  const AuxVectorData& src,
233  size_t src_index,
234  size_t n) const
235 {
236  (void)copyImpl (auxid, dst, dst_index, src, src_index, n);
237 }
238 
239 
240 
241 /**
242  * @brief Copy elements between vectors, possibly applying thinning.
243  * @param auxid The aux data item being operated on.
244  * @param dst Container for the destination vector.
245  * @param dst_index Index of the first destination element in the vector.
246  * @param src Container for the source vector.
247  * @param src_index Index of source element in the vector.
248  * @param src_index Index of the first source element in the vector.
249  * @param n Number of elements to copy.
250  *
251  * @c dst and @ src can be either the same or different.
252  */
253 template <class T, class ALLOC>
254 void AuxTypeVectorFactoryImpl<T, ALLOC>::copyForOutput (SG::auxid_t auxid,
255  AuxVectorData& dst, size_t dst_index,
256  const AuxVectorData& src, size_t src_index,
257  size_t n) const
258 {
259  [[maybe_unused]]
260  vector_value_type* dstptr = copyImpl (auxid, dst, dst_index, src, src_index, n);
261 #ifndef XAOD_STANDALONE
262  const SG::ThinningCache* tc = SG::getThinningCache();
263  for (size_t i = 0; i < n; i++) {
264  applyAuxThinning (tc, dstptr + i);
265  }
266 #endif
267 }
268 
269 
270 /**
271  * @brief Swap elements between vectors.
272  * @param auxid The aux data item being operated on.
273  * @param a Container for the first vector.
274  * @param aindex Index of the first element in the first vector.
275  * @param b Container for the second vector.
276  * @param bindex Index of the first element in the second vector.
277  * @param n Number of elements to swap.
278  *
279  * @c a and @ b can be either the same or different.
280  * However, the ranges should not overlap.
281  */
282 template <class T, class ALLOC>
283 void AuxTypeVectorFactoryImpl<T, ALLOC>::swap (SG::auxid_t auxid,
284  AuxVectorData& a, size_t aindex,
285  AuxVectorData& b, size_t bindex,
286  size_t n) const
287 {
288  if (n == 0) return;
289  auto aptr = reinterpret_cast<vector_value_type*>(a.getDataArray (auxid));
290  auto bptr = &a == &b ? aptr : reinterpret_cast<vector_value_type*>(b.getDataArray (auxid));
291  for (size_t i = 0; i < n; i++) {
292  std::swap (aptr[aindex+i], bptr[bindex+i]);
293  }
294 }
295 
296 
297 /**
298  * @brief Clear a range of elements within a vector.
299  * @param auxid The aux data item being operated on.
300  * @param dst Container holding the element
301  * @param dst_index Index of the first element in the vector.
302  * @param n Number of elements to clear.
303  */
304 template <class T, class ALLOC>
305 void AuxTypeVectorFactoryImpl<T, ALLOC>::clear (SG::auxid_t auxid,
306  AuxVectorData& dst,
307  size_t dst_index,
308  size_t n) const
309 {
310  if (n == 0) return;
311  auto ptr = reinterpret_cast<vector_value_type*>(dst.getDataArray (auxid));
312  std::fill (ptr+dst_index, ptr+dst_index+n, SG::Zero<vector_value_type>::zero());
313 }
314 
315 
316 /**
317  * @brief Return the size of an element of this vector type.
318  */
319 template <class T, class ALLOC>
320 size_t AuxTypeVectorFactoryImpl<T, ALLOC>::getEltSize() const
321 {
322  return sizeof (typename AuxTypeVector<T, ALLOC>::vector_type::value_type);
323 }
324 
325 
326 /**
327  * @brief Return the @c type_info of the vector.
328  */
329 template <class T, class ALLOC>
330 const std::type_info* AuxTypeVectorFactoryImpl<T, ALLOC>::tiVec() const
331 {
332  return &typeid (typename AuxTypeVector<T, ALLOC>::vector_type);
333 }
334 
335 
336 /**
337  * @brief True if the vectors created by this factory work by dynamic
338  * emulation (via @c TVirtualCollectionProxy or similar); false
339  * if the std::vector code is used directly.
340  */
341 template <class T, class ALLOC>
342 bool AuxTypeVectorFactoryImpl<T, ALLOC>::isDynamic() const
343 {
344  return false;
345 }
346 
347 
348 /**
349  * @brief Return the @c type_info of the vector allocator.
350  */
351 template <class T, class ALLOC>
352 const std::type_info* AuxTypeVectorFactoryImpl<T, ALLOC>::tiAlloc() const
353 {
354  return &typeid(ALLOC);
355 }
356 
357 
358 /**
359  * @brief Return the @c type_info of the vector allocator.
360  */
361 template <class T, class ALLOC>
362 std::string AuxTypeVectorFactoryImpl<T, ALLOC>::tiAllocName() const
363 {
364  return SG::normalizedTypeinfoName (typeid(ALLOC));
365 }
366 
367 
368 } // namespace SG