ATLAS Offline Software
PackedLinkVectorFactory.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/PackedLinkVectorFactory.icc
6  * @author scott snyder <snyder@bnl.gov>
7  * @date Oct, 2023
8  * @brief Factory object that creates vectors using @c AuxTypeVector,
9  * specialized for PackedLink.
10  */
11 
12 
13 #include "AthContainers/tools/AuxTypeVector.h"
14 #include "AthContainers/AuxTypeRegistry.h"
15 
16 
17 namespace SG {
18 
19 
20 /**
21  * @brief Create a vector object of this type.
22  * @param auxid ID for the variable being created.
23  * @param size Initial size of the new vector.
24  * @param capacity Initial capacity of the new vector.
25  * @param isLinked True if this variable is linked from another one.
26  * Must be false.
27  */
28 template <class CONT, class ALLOC>
29 std::unique_ptr<IAuxTypeVector>
30 PackedLinkVectorFactory<CONT, ALLOC>::create (SG::auxid_t auxid,
31  size_t size, size_t capacity,
32  [[maybe_unused]] bool isLinked) const
33 {
34  assert (!isLinked);
35  const AuxTypeRegistry& r = AuxTypeRegistry::instance();
36  auxid_t linked_id = r.linkedVariable (auxid);
37 
38  using linkedAlloc = typename std::allocator_traits<ALLOC>::template rebind_alloc<DataLink<CONT> >;
39  auto linkedVec =
40  std::make_unique<AuxTypeVector<DataLink<CONT>, linkedAlloc> > (linked_id,
41  0, 0, true);
42  return std::make_unique<AuxTypeVector_t> (auxid, size, capacity,
43  std::move (linkedVec));
44 }
45 
46 
47 /**
48  * @brief Create a vector object of this type from a data blob.
49  * @param auxid ID for the variable being created.
50  * @param data The vector object.
51  * @param linkedVector The interface for another variable linked to this one.
52  * (We do not take ownership.)
53  * @param isPacked If true, @c data is a @c PackedContainer.
54  * @param ownFlag If true, the newly-created IAuxTypeVector object
55  * will take ownership of @c data.
56  * @param isLinked True if this variable is linked from another one.
57  *
58  * @c data should be a pointer to a
59  * std::vector<SG::PackedLink<CONT>, ALLOC<...> > object obtained with new.
60  * For this method, isPacked and isLinked must both be false.
61  */
62 template <class CONT, class ALLOC>
63 std::unique_ptr<IAuxTypeVector>
64 PackedLinkVectorFactory<CONT, ALLOC>::createFromData (SG::auxid_t auxid,
65  void* data,
66  IAuxTypeVector* linkedVector,
67  [[maybe_unused]] bool isPacked,
68  bool ownFlag,
69  [[maybe_unused]] bool isLinked) const
70 {
71  assert (!isPacked && !isLinked && linkedVector != nullptr);
72  using Holder = SG::PackedLinkVectorHolder<CONT, ALLOC>;
73  using vector_type = typename Holder::vector_type;
74  return std::make_unique<Holder>
75  (auxid, reinterpret_cast<vector_type*>(data), linkedVector, ownFlag);
76 }
77 
78 
79 /**
80  * @brief Copy elements between vectors.
81  * @param auxid The aux data item being operated on.
82  * @param dst Container for the destination vector.
83  * @param dst_index Index of the first destination element in the vector.
84  * @param src Container for the source vector.
85  * @param src_index Index of the first source element in the vector.
86  * @param n Number of elements to copy.
87  *
88  * @c dst and @ src can be either the same or different.
89  */
90 template <class CONT, class ALLOC>
91 void PackedLinkVectorFactory<CONT, ALLOC>::copy (SG::auxid_t auxid,
92  AuxVectorData& dst,
93  size_t dst_index,
94  const AuxVectorData& src,
95  size_t src_index,
96  size_t n) const
97 {
98  if (n == 0) return;
99  Base::copy (auxid, dst, dst_index, src, src_index, n);
100  if (&dst != &src && src.getDataArrayAllowMissing (auxid) != nullptr) {
101  IAuxTypeVector& dstlv = *dst.getStore()->linkedVector (auxid);
102  if (!Helper::updateLinks (dstlv,
103  reinterpret_cast<vector_value_type*>(dst.getDataArray (auxid)) + dst_index,
104  n,
105  *src.getConstStore()->linkedVector (auxid),
106  nullptr))
107  {
108  dst.clearCache (dstlv.auxid());
109  }
110  }
111 }
112 
113 
114 /**
115  * @brief Copy elements between vectors, possibly applying thinning.
116  * @param auxid The aux data item being operated on.
117  * @param dst Container for the destination vector.
118  * @param dst_index Index of the first destination element in the vector.
119  * @param src Container for the source vector.
120  * @param src_index Index of source element in the vector.
121  * @param src_index Index of the first source element in the vector.
122  * @param n Number of elements to copy.
123  *
124  * @c dst and @ src can be either the same or different.
125  */
126 template <class CONT, class ALLOC>
127 void PackedLinkVectorFactory<CONT, ALLOC>::copyForOutput
128  (SG::auxid_t auxid,
129  AuxVectorData& dst, size_t dst_index,
130  const AuxVectorData& src, size_t src_index,
131  size_t n) const
132 {
133  if (n == 0) return;
134  copy (auxid, dst, dst_index, src, src_index, n);
135 #ifndef XAOD_STANDALONE
136  auto dstptr = reinterpret_cast<vector_value_type*>(dst.getDataArray (auxid)) + dst_index;
137  IAuxTypeVector& dstlv = *dst.getStore()->linkedVector (auxid);
138  typename Helper::DataLinkBase_span links = Helper::getLinkBaseSpan (dstlv);
139  const SG::ThinningCache* tc = SG::getThinningCache();
140  IProxyDict* sg = Helper::storeFromSpan (links);
141  bool cacheValid = Helper::applyThinning (dstlv, dstptr, n, links, tc, sg);
142  if (!cacheValid) dst.clearCache (dstlv.auxid());
143 #endif
144 }
145 
146 
147 /**
148  * @brief Swap elements between vectors.
149  * @param auxid The aux data item being operated on.
150  * @param a Container for the first vector.
151  * @param aindex Index of the first element in the first vector.
152  * @param b Container for the second vector.
153  * @param bindex Index of the first element in the second vector.
154  * @param n Number of elements to swap.
155  *
156  * @c a and @ b can be either the same or different.
157  * However, the ranges should not overlap.
158  */
159 template <class CONT, class ALLOC>
160 void PackedLinkVectorFactory<CONT, ALLOC>::swap (SG::auxid_t auxid,
161  AuxVectorData& a, size_t aindex,
162  AuxVectorData& b, size_t bindex,
163  size_t n) const
164 {
165  if (n == 0) return;
166  Base::swap (auxid, a, aindex, b, bindex, n);
167  if (&a != &b) {
168  IAuxTypeVector& alv = *a.getStore()->linkedVector (auxid);
169  IAuxTypeVector& blv = *b.getStore()->linkedVector (auxid);
170 
171  if (!Helper::updateLinks (alv,
172  reinterpret_cast<vector_value_type*>(a.getDataArray (auxid)) + aindex,
173  n, blv, nullptr))
174  {
175  a.clearCache (alv.auxid());
176  }
177 
178  if (!Helper::updateLinks (blv,
179  reinterpret_cast<vector_value_type*>(b.getDataArray (auxid)) + bindex,
180  n, alv, nullptr))
181  {
182  b.clearCache (blv.auxid());
183  }
184  }
185 }
186 
187 
188 //**************************************************************************
189 
190 
191 /**
192  * @brief Create a vector object of this type.
193  * @param auxid ID for the variable being created.
194  * @param size Initial size of the new vector.
195  * @param capacity Initial capacity of the new vector.
196  * @param isLinked True if this variable is linked from another one.
197  * Must be false.
198  */
199 template <class CONT, class VALLOC, class VELT, class ALLOC>
200 std::unique_ptr<IAuxTypeVector>
201 PackedLinkVVectorFactory<CONT, VALLOC, VELT, ALLOC>::
202 create (SG::auxid_t auxid,
203  size_t size, size_t capacity,
204  [[maybe_unused]] bool isLinked) const
205 {
206  assert (!isLinked);
207  const AuxTypeRegistry& r = AuxTypeRegistry::instance();
208  auxid_t linked_id = r.linkedVariable (auxid);
209 
210  using linkedAlloc = typename std::allocator_traits<ALLOC>::template rebind_alloc<DataLink<CONT> >;
211  auto linkedVec =
212  std::make_unique<AuxTypeVector<DataLink<CONT>, linkedAlloc> > (linked_id,
213  0, 0, true);
214  return std::make_unique<AuxTypeVector_t> (auxid, size, capacity,
215  std::move (linkedVec));
216 }
217 
218 
219 /**
220  * @brief Create a vector object of this type from a data blob.
221  * @param auxid ID for the variable being created.
222  * @param data The vector object.
223  * @param linkedVector The interface for another variable linked to this one.
224  * (We do not take ownership.)
225  * @param isPacked If true, @c data is a @c PackedContainer.
226  * @param ownFlag If true, the newly-created IAuxTypeVector object
227  * will take ownership of @c data.
228  * @param isLinked True if this variable is linked from another one.
229  *
230  * @c data should be a pointer to a
231  * std::vector<std::vector<SG::PackedLink<CONT>, VALLOC<...> > >, ALLOC<...> > object obtained with new.
232  * For this method, isPacked and isLinked must both be false.
233  */
234 template <class CONT, class VALLOC, class VELT, class ALLOC>
235 std::unique_ptr<IAuxTypeVector>
236 PackedLinkVVectorFactory<CONT, VALLOC, VELT, ALLOC>::
237 createFromData (SG::auxid_t auxid,
238  void* data,
239  IAuxTypeVector* linkedVector,
240  [[maybe_unused]] bool isPacked,
241  bool ownFlag,
242  [[maybe_unused]] bool isLinked) const
243 {
244  assert (!isPacked && !isLinked && linkedVector != nullptr);
245  using Holder = SG::PackedLinkVVectorHolder<CONT, VALLOC, VELT, ALLOC>;
246  using vector_type = typename Holder::vector_type;
247  return std::make_unique<Holder>
248  (auxid, reinterpret_cast<vector_type*>(data), linkedVector, ownFlag);
249 }
250 
251 
252 /**
253  * @brief Copy elements between vectors.
254  * @param auxid The aux data item being operated on.
255  * @param dst Container for the destination vector.
256  * @param dst_index Index of the first destination element in the vector.
257  * @param src Container for the source vector.
258  * @param src_index Index of the first source element in the vector.
259  * @param n Number of elements to copy.
260  *
261  * @c dst and @ src can be either the same or different.
262  */
263 template <class CONT, class VALLOC, class VELT, class ALLOC>
264 void PackedLinkVVectorFactory<CONT, VALLOC, VELT, ALLOC>::
265 copy (SG::auxid_t auxid,
266  AuxVectorData& dst,
267  size_t dst_index,
268  const AuxVectorData& src,
269  size_t src_index,
270  size_t n) const
271 {
272  if (n == 0) return;
273  Base::copy (auxid, dst, dst_index, src, src_index, n);
274  if (&dst != &src && src.getDataArrayAllowMissing (auxid) != nullptr) {
275  IAuxTypeVector& dstlv = *dst.getStore()->linkedVector (auxid);
276  if (!Helper::updateLinks (dstlv,
277  reinterpret_cast<vector_value_type*>(dst.getDataArray (auxid)) + dst_index,
278  n,
279  *src.getConstStore()->linkedVector (auxid),
280  nullptr))
281  {
282  dst.clearCache (dstlv.auxid());
283  }
284  }
285 }
286 
287 
288 /**
289  * @brief Copy elements between vectors, possibly applying thinning.
290  * @param auxid The aux data item being operated on.
291  * @param dst Container for the destination vector.
292  * @param dst_index Index of the first destination element in the vector.
293  * @param src Container for the source vector.
294  * @param src_index Index of source element in the vector.
295  * @param src_index Index of the first source element in the vector.
296  * @param n Number of elements to copy.
297  *
298  * @c dst and @ src can be either the same or different.
299  */
300 template <class CONT, class VALLOC, class VELT, class ALLOC>
301 void PackedLinkVVectorFactory<CONT, VALLOC, VELT, ALLOC>::copyForOutput
302  (SG::auxid_t auxid,
303  AuxVectorData& dst, size_t dst_index,
304  const AuxVectorData& src, size_t src_index,
305  size_t n) const
306 {
307  if (n == 0) return;
308  copy (auxid, dst, dst_index, src, src_index, n);
309 #ifndef XAOD_STANDALONE
310  using DataLinkBase_span = typename Helper::DataLinkBase_span;
311  auto dstptr = reinterpret_cast<vector_value_type*>(dst.getDataArray (auxid)) + dst_index;
312  IAuxTypeVector& dstlv = *dst.getStore()->linkedVector (auxid);
313  DataLinkBase_span links = Helper::getLinkBaseSpan (dstlv);
314  const SG::ThinningCache* tc = SG::getThinningCache();
315  IProxyDict* sg = Helper::storeFromSpan (links);
316  bool cacheValid = true;
317  for (size_t i = 0; i < n; i++) {
318  VELT& v = dstptr[i];
319  cacheValid &= Helper::applyThinning (dstlv, v.data(), v.size(),
320  links, tc, sg);
321  }
322  if (!cacheValid) dst.clearCache (dstlv.auxid());
323 #endif
324 }
325 
326 
327 /**
328  * @brief Swap elements between vectors.
329  * @param auxid The aux data item being operated on.
330  * @param a Container for the first vector.
331  * @param aindex Index of the first element in the first vector.
332  * @param b Container for the second vector.
333  * @param bindex Index of the first element in the second vector.
334  * @param n Number of elements to swap.
335  *
336  * @c a and @ b can be either the same or different.
337  * However, the ranges should not overlap.
338  */
339 template <class CONT, class VALLOC, class VELT, class ALLOC>
340 void PackedLinkVVectorFactory<CONT, VALLOC, VELT, ALLOC>::
341 swap (SG::auxid_t auxid,
342  AuxVectorData& a, size_t aindex,
343  AuxVectorData& b, size_t bindex,
344  size_t n) const
345 {
346  if (n == 0) return;
347  Base::swap (auxid, a, aindex, b, bindex, n);
348  if (&a != &b) {
349  IAuxTypeVector& alv = *a.getStore()->linkedVector (auxid);
350  IAuxTypeVector& blv = *b.getStore()->linkedVector (auxid);
351 
352  if (!Helper::updateLinks (alv,
353  reinterpret_cast<vector_value_type*>(a.getDataArray (auxid)) + aindex,
354  n, blv, nullptr))
355  {
356  a.clearCache (alv.auxid());
357  }
358 
359  if (!Helper::updateLinks (blv,
360  reinterpret_cast<vector_value_type*>(b.getDataArray (auxid)) + bindex,
361  n, alv, nullptr))
362  {
363  b.clearCache (blv.auxid());
364  }
365  }
366 }
367 
368 
369 } // namespace SG