ATLAS Offline Software
Loading...
Searching...
No Matches
PackedLinkVectorHelper.icc
Go to the documentation of this file.
1/*
2 * Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration.
3 */
4/**
5 * @file AthContainers/tools/PackedLinkVectorHelper.icc
6 * @author scott snyder <snyder@bnl.gov>
7 * @date May, 2024
8 * @brief Helper functions for managing @c PackedLink variables.
9 */
10
11
12namespace SG::detail {
13
14
15/**
16 * @brief Constructor from an @c IAuxTypeVector directly.
17 * @param linkedVector The @c IAuxTypeVector for the aux variable.
18 */
19inline
20PackedLinkVectorHelperBase::LinkedVector::LinkedVector (IAuxTypeVector& linkedVector)
21 : m_data (&linkedVector)
22{
23}
24
25
26/**
27 * @brief Constructor from a container and aux ID.
28 * @param container Container holding the variables.
29 * @param auxid The ID of the PackedLink variable.
30 */
31inline
32PackedLinkVectorHelperBase::LinkedVector::LinkedVector (AuxVectorData& container, SG::auxid_t auxid)
33 : m_data (std::make_pair (&container, auxid))
34{
35}
36
37
38/**
39 * @brief Return the @c IAuxTypeVector.
40 */
41inline
42IAuxTypeVector* PackedLinkVectorHelperBase::LinkedVector::get()
43{
44 // If we already have it, return it.
45 if (m_data.index() == 0)
46 return std::get<0>(m_data);
47
48 // Look it up from the container.
49 auto [container, auxid] = std::get<1>(m_data);
50 IAuxTypeVector* lv = container->getStore()->linkedVector (auxid);
51
52 // Remember it to possibly use again.
53 m_data = lv;
54 return lv;
55}
56
57
58/**
59 * @brief Return the @c IAuxTypeVector.
60 */
61inline
62IAuxTypeVector&
63PackedLinkVectorHelperBase::LinkedVector::operator*()
64{
65 return *get();
66}
67
68
69/**
70 * @brief Return the @c IAuxTypeVector.
71 */
72inline
73IAuxTypeVector* PackedLinkVectorHelperBase::LinkedVector::operator->()
74{
75 return get();
76}
77
78
79/**
80 * @brief Return the current store from the first valid link in the span.
81 * If there are no valid links, then return the global default.
82 * @param links The span of links.
83 */
84inline
85auto PackedLinkVectorHelperBase::storeFromSpan ([[maybe_unused]] DataLinkBase_span& links)
86 -> IProxyDict*
87{
88#ifndef XAOD_STANDALONE
89 if (links.size() > 1) {
90 return links[1].source();
91 }
92#endif
93 return CurrentEventStore::store();
94}
95
96
97/**
98 * @brief Return a span over all the linked @c DataLinkBase's.
99 * from the linked vector.
100 * @param linkedVec Interface for the linked vector of @c DataLinkBase's.
101 */
102inline
103auto PackedLinkVectorHelperBase::getLinkBaseSpan (IAuxTypeVector& linkedVec)
104 -> DataLinkBase_span
105{
106 return DataLinkBase_span (linkedVec.getDataSpan());
107}
108
109
110/**
111 * @brief Return a span over all the linked @c DataLinkBase's.
112 * from the linked vector.
113 * @param linkedVec Interface for the linked vector of @c DataLinkBase's.
114 */
115inline
116auto PackedLinkVectorHelperBase::getLinkBaseSpan (const IAuxTypeVector& linkedVec)
117 -> const_DataLinkBase_span
118{
119 return const_DataLinkBase_span (linkedVec.getDataSpan());
120}
121
122
123/**
124 * @brief Find the collection index in the linked DataLinks for a sgkey.
125 * @param linkedVec How to find the linked vector.
126 * @param sgkey Hashed key for which to search.
127 * @param links Span over the vector of @c DataLinks, as @c DataLinkBase.
128 * May be modified if the vector grows.
129 * @param sg The @c IProxyDict of the current store.
130 * May be null to use the global, thread-local default.
131 *
132 * Searches for a @c DataLink matching @c sgkey in the linked vector.
133 * If not found, then a new entry is added.
134 * Returns a pair (INDEX, CACHEVALID). INDEX is the index in the vector
135 * of the sgkey (and thus the collection index to store in the @c PackedLink).
136 * CACHEVALID is true if it is known that the payload of the vector
137 * has not moved. (If this is false, any caches/iterators must be assumed
138 * to be invalid.)
139 */
140template <class CONT>
141inline
142std::pair<size_t, bool> PackedLinkVectorHelper<CONT>::findCollection
143 (LinkedVector& linkedVec,
144 sgkey_t sgkey, DataLinkBase_span& links, IProxyDict* sg)
145{
146 return findCollectionBase (linkedVec, sgkey, links, sg, initLink);
147}
148
149
150/**
151 * @brief Update collection index of a collection of @c PackedLink.
152 * @param linkedVec Interface for the linked vector of DataLinks.
153 * @param ptr Pointer to the start of the PackedLink collection.
154 * @param n Length of the PackedLink collection.
155 * @param srcDLinks Span over the vector of DataLinks
156 * for the source container of the links.
157 * @param sg The @c IProxyDict of the current store.
158 * If null, take it from the links in @c srcDlinks,
159 * or use the global, thread-local default.
160 *
161 * To be used after links have been copied/moved from one container
162 * to another. The collection indices are updated to be appropriate
163 * for the destination container.
164 * Returns true if it is known that the payload of the linked vector
165 * has not moved. (If this is false, any caches/iterators must be assumed
166 * to be invalid.)
167 */
168template <class CONT>
169inline
170bool PackedLinkVectorHelper<CONT>::updateLinks (IAuxTypeVector& linkedVec,
171 SG::PackedLink<CONT>* ptr,
172 size_t n,
173 const const_DataLinkBase_span& srcDLinks,
174 IProxyDict* sg)
175{
176 PackedLinkBase_span span (static_cast<PackedLinkBase*>(ptr), n);
177 return updateLinksBase (linkedVec, span, srcDLinks, sg, initLink);
178}
179
180
181/**
182 * @brief Update collection index of a collection of @c PackedLink.
183 * @param linkedVec Interface for the linked vector of DataLinks.
184 * @param ptr Pointer to the start of the PackedLink collection.
185 * @param n Length of the PackedLink collection.
186 * @param srclv Interface for the linked vector
187 * for the source container of the links.
188 * @param sg The @c IProxyDict of the current store.
189 * If null, take it from the links in @c srcDlinks,
190 * or use the global, thread-local default.
191 *
192 * To be used after links have been copied/moved from one container
193 * to another. The collection indices are updated to be appropriate
194 * for the destination container.
195 * Returns true if it is known that the payload of the linked vector
196 * has not moved. (If this is false, any caches/iterators must be assumed
197 * to be invalid.)
198 */
199template <class CONT>
200inline
201bool PackedLinkVectorHelper<CONT>::updateLinks (IAuxTypeVector& linkedVec,
202 SG::PackedLink<CONT>* ptr,
203 size_t n,
204 const IAuxTypeVector& srclv,
205 IProxyDict* sg)
206{
207 const_DataLinkBase_span srcDLinks = getLinkBaseSpan (srclv);
208 PackedLinkBase_span span (static_cast<PackedLinkBase*>(ptr), n);
209 return updateLinksBase (linkedVec, span, srcDLinks, sg, initLink);
210}
211
212
213/**
214 * @brief Update collection index of a collection of @c PackedLink vectors.
215 * @param linkedVec Interface for the linked vector of DataLinks.
216 * @param ptr Pointer to the start of the PackedLink vector collection.
217 * @param n Length of the PackedLink vector collection.
218 * @param srclv Interface for the linked vector
219 * for the source container of the links.
220 * @param sg The @c IProxyDict of the current store.
221 * If null, take it from the links in @c srcDlinks,
222 * or use the global, thread-local default.
223 *
224 * To be used after links have been copied/moved from one container
225 * to another. The collection indices are updated to be appropriate
226 * for the destination container.
227 * Returns true if it is known that the payload of the linked vector
228 * has not moved. (If this is false, any caches/iterators must be assumed
229 * to be invalid.)
230 */
231template <class CONT>
232template <class VALLOC>
233bool PackedLinkVectorHelper<CONT>::updateLinks (IAuxTypeVector& linkedVec,
234 std::vector<SG::PackedLink<CONT>, VALLOC>* ptr,
235 size_t n,
236 const IAuxTypeVector& srclv,
237 IProxyDict* sg)
238{
239 const_DataLinkBase_span srcDLinks = getLinkBaseSpan (srclv);
240 if (sg == nullptr) {
241 DataLinkBase_span DLinks (getLinkBaseSpan (linkedVec));
242 sg = storeFromSpan (DLinks);
243 }
244 bool cacheValid = true;
245 for (size_t i = 0; i < n; i++) {
246 PackedLinkBase_span span (static_cast<PackedLinkBase*>(ptr[i].data()),
247 ptr[i].size());
248 cacheValid &= updateLinksBase (linkedVec, span, srcDLinks, sg, initLink);
249 }
250 return cacheValid;
251}
252
253
254/**
255 * @brief Assign a range of @c ElementLink to a vector of @c Packedlink.
256 * @param vect The vector of @c PackedLink to which to assign.
257 * @param linkedVec Interface for the linked vector of DataLinks.
258 * @param dlinks Span over the link vector, as @c DataLinkBase.
259 * @param x The range to assign.
260 *
261 * Returns true if it is known that the payload of the linked vector
262 * has not moved. (If this is false, any caches/iterators must be assumed
263 * to be invalid.)
264 */
265template <class CONT>
266template <class VALLOC, ElementLinkRange<CONT> RANGE>
267bool
268PackedLinkVectorHelper<CONT>::assignVElt (std::vector<PLink_t, VALLOC>& velt,
269 IAuxTypeVector& linkedVec,
270 DataLinkBase_span& dlinks,
271 const RANGE& x)
272{
273 // Define a ElementLink->PackedLink transform.
274 bool cacheValid = true;
275 LinkedVector lv (linkedVec);
276 auto xform = [&] (const Link_t& el) {
277 auto [dlindex, flag] = findCollection (lv,
278 el.key(),
279 dlinks,
280 el.source());
281 cacheValid &= flag;
282 return PackedLink<CONT> (dlindex, el.isDefault() ? 0 : el.index());
283 };
284
285 // Make a transformed range and assign it to the vector.
286#ifdef __cpp_lib_containers_ranges // c++23
287 velt.assign_range (x | std::views::transform (xform));
288#else
289 const auto r = x | std::views::transform (xform);
290 velt.assign (r.begin(), r.end());
291#endif
292 return cacheValid;
293}
294
295
296/**
297 * @brief Insert a range of @c ElementLink into a vector of @c Packedlink.
298 * @param vect The vector of @c PackedLink to which to assign.
299 * @param pos The position at which to do the insertion.
300 * @param linkedVec Interface for the linked vector of DataLinks.
301 * @param dlinks Span over the link vector, as @c DataLinkBase.
302 * @param x The range to assign.
303 *
304 * Returns true if it is known that the payload of the linked vector
305 * has not moved. (If this is false, any caches/iterators must be assumed
306 * to be invalid.)
307 */
308template <class CONT>
309template <class VALLOC, ElementLinkRange<CONT> RANGE>
310bool
311PackedLinkVectorHelper<CONT>::insertVElt (std::vector<PLink_t, VALLOC>& velt,
312 size_t pos,
313 IAuxTypeVector& linkedVec,
314 DataLinkBase_span& dlinks,
315 const RANGE& x)
316{
317 // Define a ElementLink->PackedLink transform.
318 bool cacheValid = true;
319 LinkedVector lv (linkedVec);
320 auto xform = [&] (const Link_t& el) {
321 auto [dlindex, flag] = findCollection (lv,
322 el.key(),
323 dlinks,
324 el.source());
325 cacheValid &= flag;
326 return PackedLink<CONT> (dlindex, el.isDefault() ? 0 : el.index());
327 };
328
329 // Make a transformed range and assign it to the vector.
330#ifdef __cpp_lib_containers_ranges // c++23
331 velt.insert_range (velt.begin()+pos, x | std::views::transform (xform));
332#else
333 const auto r = x | std::views::transform (xform);
334 velt.insert (velt.begin()+pos, r.begin(), r.end());
335#endif
336 return cacheValid;
337}
338
339
340#ifndef XAOD_STANDALONE
341/**
342 * @brief Apply thinning to packed links, to prepare them for output.
343 * @param linkedVec Interface for the linked vector of @c DataLinks.
344 * @param ptr Pointer to the start of the PackedLink collection.
345 * @param n Length of the PackedLink collection.
346 * @param dlinks Span over the source link vector, as @c DataLinkBase.
347 * @param tc The @c ThinningCache for this object, if it exists.
348 * @param sg The @c IProxyDict of the current store.
349 * If null, take it from the links in @c srcDlinks,
350 * or use the global, thread-local default.
351 *
352 * Returns true if it is known that the payload of the linked vector
353 * has not moved. (If this is false, any caches/iterators must be assumed
354 * to be invalid.)
355 */
356template <class CONT>
357inline
358bool
359PackedLinkVectorHelper<CONT>::applyThinning (IAuxTypeVector& linkedVec,
360 PackedLink<CONT>* ptr,
361 size_t n,
362 DataLinkBase_span& dlinks,
363 const SG::ThinningCache* tc,
364 IProxyDict* sg)
365{
366 PackedLinkBase_span lspan (static_cast<PackedLinkBase*>(ptr), n);
367 return applyThinningBase (linkedVec, lspan, dlinks, tc, sg, initLink);
368}
369#endif
370
371
372/**
373 * @brief Initialize a @c DataLink.
374 * @param dl The link to initialize. Really of type @c DLink_t.
375 * @param sgkey Hashed key to which to initialize the link.
376 * @param sg The @c IProxyDict of the current store.
377 * May be null to use the global, thread-local default.
378 */
379template <class CONT>
380inline
381void PackedLinkVectorHelper<CONT>::initLink (DataLinkBase& dl,
382 sgkey_t sgkey,
383 [[maybe_unused]] IProxyDict* sg)
384{
385#ifdef XAOD_STANDALONE
386 dl.setPersKey (sgkey);
387#else
388 static_cast<DLink_t&>(dl).toIdentifiedObject (sgkey, sg);
389#endif
390}
391
392
393} // namespace SG::detail