ATLAS Offline Software
Loading...
Searching...
No Matches
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
17namespace 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 */
28template <class CONT, class ALLOC>
29std::unique_ptr<IAuxTypeVector>
30PackedLinkVectorFactory<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 */
62template <class CONT, class ALLOC>
63std::unique_ptr<IAuxTypeVector>
64PackedLinkVectorFactory<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 */
90template <class CONT, class ALLOC>
91void 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 */
126template <class CONT, class ALLOC>
127void 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 */
159template <class CONT, class ALLOC>
160void 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 */
199template <class CONT, class VALLOC, class VELT, class ALLOC>
200std::unique_ptr<IAuxTypeVector>
201PackedLinkVVectorFactory<CONT, VALLOC, VELT, ALLOC>::
202create (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 */
234template <class CONT, class VALLOC, class VELT, class ALLOC>
235std::unique_ptr<IAuxTypeVector>
236PackedLinkVVectorFactory<CONT, VALLOC, VELT, ALLOC>::
237createFromData (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 */
263template <class CONT, class VALLOC, class VELT, class ALLOC>
264void PackedLinkVVectorFactory<CONT, VALLOC, VELT, ALLOC>::
265copy (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 */
300template <class CONT, class VALLOC, class VELT, class ALLOC>
301void 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 */
339template <class CONT, class VALLOC, class VELT, class ALLOC>
340void PackedLinkVVectorFactory<CONT, VALLOC, VELT, ALLOC>::
341swap (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