2 * Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration.
5 * @file AthContainers/tools/PackedLinkVectorHelper.icc
6 * @author scott snyder <snyder@bnl.gov>
8 * @brief Helper functions for managing @c PackedLink variables.
12 namespace SG::detail {
16 * @brief Constructor from an @c IAuxTypeVector directly.
17 * @param linkedVector The @c IAuxTypeVector for the aux variable.
20 PackedLinkVectorHelperBase::LinkedVector::LinkedVector (IAuxTypeVector& linkedVector)
21 : m_data (&linkedVector)
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.
32 PackedLinkVectorHelperBase::LinkedVector::LinkedVector (AuxVectorData& container, SG::auxid_t auxid)
33 : m_data (std::make_pair (&container, auxid))
39 * @brief Return the @c IAuxTypeVector.
42 IAuxTypeVector* PackedLinkVectorHelperBase::LinkedVector::get()
44 // If we already have it, return it.
45 if (m_data.index() == 0)
46 return std::get<0>(m_data);
48 // Look it up from the container.
49 auto [container, auxid] = std::get<1>(m_data);
50 IAuxTypeVector* lv = container->getStore()->linkedVector (auxid);
52 // Remember it to possibly use again.
59 * @brief Return the @c IAuxTypeVector.
63 PackedLinkVectorHelperBase::LinkedVector::operator*()
70 * @brief Return the @c IAuxTypeVector.
73 IAuxTypeVector* PackedLinkVectorHelperBase::LinkedVector::operator->()
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.
85 auto PackedLinkVectorHelperBase::storeFromSpan ([[maybe_unused]] DataLinkBase_span& links)
88 #ifndef XAOD_STANDALONE
89 if (links.size() > 1) {
90 return links[1].source();
93 return CurrentEventStore::store();
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.
103 auto PackedLinkVectorHelperBase::getLinkBaseSpan (IAuxTypeVector& linkedVec)
106 return DataLinkBase_span (linkedVec.getDataSpan());
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.
116 auto PackedLinkVectorHelperBase::getLinkBaseSpan (const IAuxTypeVector& linkedVec)
117 -> const_DataLinkBase_span
119 return const_DataLinkBase_span (linkedVec.getDataSpan());
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.
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
140 template <class CONT>
142 std::pair<size_t, bool> PackedLinkVectorHelper<CONT>::findCollection
143 (LinkedVector& linkedVec,
144 sgkey_t sgkey, DataLinkBase_span& links, IProxyDict* sg)
146 return findCollectionBase (linkedVec, sgkey, links, sg, initLink);
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.
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
168 template <class CONT>
170 bool PackedLinkVectorHelper<CONT>::updateLinks (IAuxTypeVector& linkedVec,
171 SG::PackedLink<CONT>* ptr,
173 const const_DataLinkBase_span& srcDLinks,
176 PackedLinkBase_span span (static_cast<PackedLinkBase*>(ptr), n);
177 return updateLinksBase (linkedVec, span, srcDLinks, sg, initLink);
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.
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
199 template <class CONT>
201 bool PackedLinkVectorHelper<CONT>::updateLinks (IAuxTypeVector& linkedVec,
202 SG::PackedLink<CONT>* ptr,
204 const IAuxTypeVector& srclv,
207 const_DataLinkBase_span srcDLinks = getLinkBaseSpan (srclv);
208 PackedLinkBase_span span (static_cast<PackedLinkBase*>(ptr), n);
209 return updateLinksBase (linkedVec, span, srcDLinks, sg, initLink);
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.
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
231 template <class CONT>
232 template <class VALLOC>
233 bool PackedLinkVectorHelper<CONT>::updateLinks (IAuxTypeVector& linkedVec,
234 std::vector<SG::PackedLink<CONT>, VALLOC>* ptr,
236 const IAuxTypeVector& srclv,
239 const_DataLinkBase_span srcDLinks = getLinkBaseSpan (srclv);
241 DataLinkBase_span DLinks (getLinkBaseSpan (linkedVec));
242 sg = storeFromSpan (DLinks);
244 bool cacheValid = true;
245 for (size_t i = 0; i < n; i++) {
246 PackedLinkBase_span span (static_cast<PackedLinkBase*>(ptr[i].data()),
248 cacheValid &= updateLinksBase (linkedVec, span, srcDLinks, sg, initLink);
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.
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
265 template <class CONT>
266 template <class VALLOC, ElementLinkRange<CONT> RANGE>
268 PackedLinkVectorHelper<CONT>::assignVElt (std::vector<PLink_t, VALLOC>& velt,
269 IAuxTypeVector& linkedVec,
270 DataLinkBase_span& dlinks,
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,
282 return PackedLink<CONT> (dlindex, el.isDefault() ? 0 : el.index());
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));
289 const auto r = x | std::views::transform (xform);
290 velt.assign (r.begin(), r.end());
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.
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
308 template <class CONT>
309 template <class VALLOC, ElementLinkRange<CONT> RANGE>
311 PackedLinkVectorHelper<CONT>::insertVElt (std::vector<PLink_t, VALLOC>& velt,
313 IAuxTypeVector& linkedVec,
314 DataLinkBase_span& dlinks,
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,
326 return PackedLink<CONT> (dlindex, el.isDefault() ? 0 : el.index());
329 // Make a transformed range and assign it to the vector.
330 #ifdef __cpp_lib_containers_ranges // c++23
331 velt.assign_range (velt.begin()+pos, x | std::views::transform (xform));
333 const auto r = x | std::views::transform (xform);
334 velt.insert (velt.begin()+pos, r.begin(), r.end());
340 #ifndef XAOD_STANDALONE
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.
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
356 template <class CONT>
359 PackedLinkVectorHelper<CONT>::applyThinning (IAuxTypeVector& linkedVec,
360 PackedLink<CONT>* ptr,
362 DataLinkBase_span& dlinks,
363 const SG::ThinningCache* tc,
366 PackedLinkBase_span lspan (static_cast<PackedLinkBase*>(ptr), n);
367 return applyThinningBase (linkedVec, lspan, dlinks, tc, sg, initLink);
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.
379 template <class CONT>
381 void PackedLinkVectorHelper<CONT>::initLink (DataLinkBase& dl,
383 [[maybe_unused]] IProxyDict* sg)
385 #ifdef XAOD_STANDALONE
386 dl.setPersKey (sgkey);
388 static_cast<DLink_t&>(dl).toIdentifiedObject (sgkey, sg);
393 } // namespace SG::detail