ATLAS Offline Software
Loading...
Searching...
No Matches
VariantLinkColumn.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7
8#ifndef COLUMNAR_VARIANT_VARIANT_LINK_COLUMN_H
9#define COLUMNAR_VARIANT_VARIANT_LINK_COLUMN_H
10
15
16namespace columnar
17{
37
38 template<ContainerIdConcept CIBase,ContainerIdConcept... CIList>
39 class ObjectLink<VariantContainerId<CIBase,CIList...>,ColumnarModeXAOD> final
40 {
43 public:
44
45 using CI = VariantContainerId<CIBase,CIList...>;
47
49
50 ObjectLink (const LinkType* val_link)
51 : m_link (val_link)
52 {}
53
54 const typename CI::xAODObjectIdType* getXAODObject () const
55 {
56 if (m_link->isValid())
57 {
58 return **m_link;
59 } else
60 {
61 return nullptr;
62 }
63 }
64
66 explicit operator bool () const
67 {
68 return m_link->isValid();
69 }
70
72 [[nodiscard]] bool has_value () const
73 {
74 return m_link->isValid();
75 }
76
78 [[nodiscard]] OptObjectId<CI,CM> opt_value () const
79 {
81 }
82
88 template<ContainerIdConcept CI2>
89 [[nodiscard]] bool isContainer () const
90 {
91 static constexpr unsigned variantIndex = CI::template getVariantIndex<CI2>();
92 static_assert (variantIndex < CI::numVariants, "invalid container id");
93 return m_link->isValid() && dynamic_cast<typename CI2::xAODObjectRangeType*>(m_link->getStorableObjectPointer());
94 }
95
97 template<ContainerIdConcept CI2>
98 [[nodiscard]] bool operator == (ObjectId<CI2,CM> id) const
99 {
100 static constexpr unsigned variantIndex = CI::template getVariantIndex<CI2>();
101 static_assert (variantIndex < CI::numVariants, "invalid container id");
102 return m_link->isValid() && (**m_link) == &id.getXAODObject();
103 }
104
110 [[nodiscard]] bool operator == (const ObjectLink<CI,CM>& obj) const
111 {
112 return getXAODObject() == obj.getXAODObject();
113 }
114
116 template<ContainerIdConcept CI2>
117 [[nodiscard]] OptObjectId<CI2,CM> tryGetVariant () const
118 {
119 static constexpr unsigned variantIndex = CI::template getVariantIndex<CI2>();
120 static_assert (variantIndex < CI::numVariants, "invalid container id");
121 if (m_link->isValid())
122 {
123 return OptObjectId<CI2,CM> (dynamic_cast<const typename CI2::xAODObjectIdType*>(**m_link));
124 } else
125 return OptObjectId<CI2,CM> ();
126 }
127
130 private:
131
132 const LinkType* m_link = nullptr;
133 };
134 template<typename... CIList>
136 {
137 return str << obj.getXAODObject() << "/" << obj.getXAODObject()->type();
138 }
139
140 namespace detail
141 {
142 // in xAOD mode we can do a fairly straightforward conversion from
143 // ElementLink as the logic is inside ObjectLink
144 template<ContainerIdConcept CIBase,typename... CIList>
146 {
149 public:
150
151 using CI = VariantContainerId<CIBase,CIList...>;
153 static constexpr bool isDefined = true;
154 static constexpr bool viewIsReference = false;
155 static constexpr bool hasSetter = true;
157
158 static void updateColumnInfo (ColumnInfo& /*info*/) {}
159
160 [[nodiscard]] static auto makeViewer (void**)
161 {
162 return [] (const ElementLink<typename CI::xAODElementLinkType>& value) {
163 return ObjectLink<VariantContainerId<CIBase,CIList...>,ColumnarModeXAOD> (&value);
164 };
165 }
166
167 struct Setter final
168 {
169 template<ContainerIdConcept CI2>
170 requires (CI::template isValidContainer<CI2>())
171 auto operator() (MemoryType& link, const ObjectId<CI2,ColumnarModeXAOD>& obj)
172 {
173 auto* container = static_cast<const typename CIBase::xAODElementLinkType*>(obj.getXAODObjectNoexcept().container());
174 link = MemoryType(*container, obj.getXAODObjectNoexcept().index());
175 }
176 };
177 [[nodiscard]] static auto makeSetter (void**)
178 {
179 return Setter{};
180 }
181 };
182 }
183
184
185
186 template<ContainerIdConcept CIBase,ContainerIdConcept... CIList, ColumnarArrayMode CM>
187 class ObjectLink<VariantContainerId<CIBase,CIList...>,CM> final
188 {
191 public:
192
193 using CI = VariantContainerId<CIBase,CIList...>;
194
195 ObjectLink (typename CM::LinkIndexType val_link, const typename CM::LinkKeyType* val_keys, void** val_dataArea)
196 : m_link (val_link), m_keys (val_keys), m_dataArea (val_dataArea)
197 {}
198
199 const typename CI::xAODObjectIdType* getXAODObject () const
200 {
201 throw std::logic_error ("can't call xAOD function in columnar mode");
202 }
203
205 explicit operator bool () const noexcept
206 {
207 return m_link != invalidObjectIndex;
208 }
209
211 [[nodiscard]] bool has_value () const noexcept
212 {
213 return m_link != invalidObjectIndex;
214 }
215
217 [[nodiscard]] OptObjectId<CI,CM> opt_value () const
218 {
219 if (m_link == CM::invalidLinkValue)
220 return OptObjectId<CI,CM> ();
221 const auto key = getLinkKey();
222 for (unsigned i = 0; i < CI::numVariants; ++ i)
223 {
224 if (m_keys[i] == key)
226 }
227 // not sure whether we should throw here or return a nullopt, but
228 // throwing is probably the safer default. if it becomes an issue
229 // we can revisit this.
230 throw std::runtime_error ("link key does not match any known container: " + std::to_string(key));
231 }
232
238 template<ContainerIdConcept CI2>
239 [[nodiscard]] bool isContainer () const
240 {
241 static constexpr unsigned variantIndex = CI::template getVariantIndex<CI2>();
242 static_assert (variantIndex < CI::numVariants, "invalid container id");
243 return getLinkKey() == m_keys[variantIndex];
244 }
245
247 template<ContainerIdConcept CI2>
248 [[nodiscard]] bool operator == (ObjectId<CI2,CM> id) const
249 {
250 static constexpr unsigned variantIndex = CI::template getVariantIndex<CI2>();
251 static_assert (variantIndex < CI::numVariants, "invalid container id");
252 return getLinkIndex() == id.getIndex() && getLinkKey() == m_keys[variantIndex];
253 }
254
260 [[nodiscard]] bool operator == (const ObjectLink<CI,CM>& obj) const
261 {
262 if (m_keys == obj.m_keys)
263 return m_link == obj.m_link;
264 if (getLinkIndex() != obj.getLinkIndex())
265 return false;
266 const auto thisKey = getLinkKey();
267 const auto thatKey = obj.getLinkKey();
268 for (unsigned i = 0; i < CI::numVariants; ++ i)
269 {
270 if (m_keys[i] == thisKey)
271 {
272 if (obj.m_keys[i] == thatKey)
273 return true;
274 else
275 return false;
276 } else if (obj.m_keys[i] == thatKey)
277 return false;
278 }
279 return false;
280 }
281
283 template<ContainerIdConcept CI2>
284 [[nodiscard]] OptObjectId<CI2,CM> tryGetVariant () const
285 {
286 static constexpr unsigned variantIndex = CI::template getVariantIndex<CI2>();
287 static_assert (variantIndex < CI::numVariants, "invalid container id");
288 if (getLinkKey() == m_keys[variantIndex])
290 else
291 return OptObjectId<CI2,CM> ();
292 }
293
294 [[nodiscard]] auto getLinkIndex () const noexcept
295 {
296 return CM::getLinkIndex (m_link);
297 }
298
299 [[nodiscard]] auto getLinkKey () const noexcept
300 {
301 return CM::getLinkKey (m_link);
302 }
303
306 private:
307
308 typename CM::LinkIndexType m_link = 0;
309 const CM::LinkKeyType* m_keys = nullptr;
310 void** m_dataArea = nullptr;
311 };
312 template<typename... CIList, ColumnarArrayMode CM>
313 std::ostream& operator<< (std::ostream& str, const ObjectLink<VariantContainerId<CIList...>,CM>& obj)
314 {
315 return str << obj.getLinkKey() << "/" << obj.getLinkIndex();
316 }
317
318
319
320 namespace detail
321 {
322 // in Array mode we need to use a vector column, as well as an
323 // extra column to contain our keys in order.
324 template<ColumnAccessMode CAM,ContainerIdConcept CIBase,ContainerIdConcept... CIList, ColumnarArrayMode CM>
325 class ContainerFreeAccessor<ObjectLink<VariantContainerId<CIBase,CIList...>,CM>,CAM,CM> final
326 {
329 public:
330
331 using VariantCI = VariantContainerId<CIBase,CIList...>;
332 static constexpr std::array containerIdNames = {CIList::idName...};
333
334 static constexpr bool isDefined = true;
335 static constexpr unsigned internalOffsetColumns = 0;
336
338
339 ContainerFreeAccessor (ColumnarTool<CM>& columnarTool, ColumnAccessorOptions&& options, ColumnAccessorOptionsArray&& optionsArray)
340 {
341 std::string dataName = optionsArray.baseName + optionsArray.dataSuffix;
342 std::string keysName = optionsArray.baseName + ".keys";
343
344 auto dataInfo = options.makeColumnInfo();
345 dataInfo.offsetName = optionsArray.offsetName;
346 dataInfo.isVariantLink = true;
347
348 auto keyInfo = options.makeColumnInfo();
349 keyInfo.accessMode = ColumnAccessMode::input;
350 keyInfo.fixedDimensions.push_back (VariantCI::numVariants);
351 keyInfo.keyColumnForVariantLink = dataName;
352 keyInfo.variantLinkTargetNames.reserve (VariantCI::numVariants);
353 for (unsigned i = 0; i < VariantCI::numVariants; ++ i)
354 keyInfo.variantLinkTargetNames.emplace_back (containerIdNames[i]);
355
356 m_dataData = std::make_unique<ColumnAccessorDataArray> (&m_dataIndex, &m_dataData, &typeid (typename CM::LinkIndexType), CAM);
357 columnarTool.addColumn (dataName, m_dataData.get(), std::move (dataInfo));
358 m_keysData = std::make_unique<ColumnAccessorDataArray> (&m_keysIndex, &m_keysData, &typeid (typename CM::LinkKeyType), ColumnAccessMode::input);
359 columnarTool.addColumn (keysName, m_keysData.get(), std::move (keyInfo));
360 }
361
363 {
364 moveAccessor (m_dataIndex, m_dataData, that.m_dataIndex, that.m_dataData);
365 moveAccessor (m_keysIndex, m_keysData, that.m_keysIndex, that.m_keysData);
366 }
367
369 {
370 if (this != &that)
371 {
372 moveAccessor (m_dataIndex, m_dataData, that.m_dataIndex, that.m_dataData);
373 moveAccessor (m_keysIndex, m_keysData, that.m_keysIndex, that.m_keysData);
374 }
375 return *this;
376 }
377
378 auto operator () (void** dataArea, std::size_t index) const noexcept
379 requires (CAM == ColumnAccessMode::input)
380 {
381 auto *data = static_cast<const typename CM::LinkIndexType*>(dataArea[m_dataIndex]);
382 auto *keys = static_cast<const typename CM::LinkKeyType*>(dataArea[m_keysIndex]);
383 return ObjectLink<VariantContainerId<CIBase,CIList...>,CM> (data[index], keys, dataArea);
384 }
385
386 [[nodiscard]] auto operator () (void** dataArea, std::size_t beginIndex, std::size_t endIndex) const noexcept
387 requires (CAM == ColumnAccessMode::input)
388 {
389 auto *data = static_cast<const typename CM::LinkIndexType*>(dataArea[m_dataIndex]);
390 auto *keys = static_cast<const typename CM::LinkKeyType*>(dataArea[m_keysIndex]);
391 return detail::VectorConvertView ([dataArea, keys](const auto& value) {return ObjectLink<VariantContainerId<CIBase,CIList...>,CM> (value, keys, dataArea);}, std::span<const typename CM::LinkIndexType>(data+beginIndex, endIndex-beginIndex));
392 }
393
394 template<ContainerIdConcept CI2>
395 requires (CAM == ColumnAccessMode::output && VariantCI::template isValidContainer<CI2>())
396 void set (void** dataArea, std::size_t index, ObjectId<CI2,CM> obj) const noexcept
397 {
398 auto *data = static_cast<typename CM::LinkIndexType*>(dataArea[m_dataIndex]);
399 auto *keys = static_cast<const typename CM::LinkKeyType*>(dataArea[m_keysIndex]);
400 data[index] = CM::mergeLinkKeyIndex (keys[VariantCI::template getVariantIndex<CI2>()], obj.getIndex());
401 }
402
403 [[nodiscard]] bool isAvailable (void** dataArea) const noexcept
404 {
405 auto *data = static_cast<const typename CM::LinkIndexType*>(dataArea[m_dataIndex]);
406 return data != nullptr;
407 }
408
409
410
413 private:
414
415 unsigned m_dataIndex = 0u;
416 std::unique_ptr<ColumnAccessorDataArray> m_dataData;
417 unsigned m_keysIndex = 0u;
418 std::unique_ptr<ColumnAccessorDataArray> m_keysData;
419 };
420
421
422
423 template<ContainerIdConcept CIBase,ContainerIdConcept... CIList,typename ELT>
425 {
428 public:
429
430 using CI = VariantContainerId<CIBase,CIList...>;
434
435 static constexpr bool isDefined = true;
436 static constexpr unsigned internalOffsetColumns = BaseAccessor::internalOffsetColumns;
437
439
440 ContainerFreeAccessor (ColumnarTool<CM>& columnarTool, ColumnAccessorOptions&& options, ColumnAccessorOptionsArray&& optionsArray)
441 : m_accessor (columnarTool, std::move (options), std::move (optionsArray))
442 {}
443
444 auto operator () (void** dataArea, std::size_t index) const noexcept
445 {
446 return m_accessor(dataArea, index).opt_value();
447 }
448
449 auto operator () (void** dataArea, std::size_t beginIndex, std::size_t endIndex) const noexcept
450 {
451 return VectorConvertView ([] (const ObjectLink<CI,CM>& link) {return link.opt_value();},
452 m_accessor(dataArea, beginIndex, endIndex));
453 }
454
455 bool isAvailable (void** dataArea) const noexcept
456 {
457 return m_accessor.isAvailable (dataArea);
458 }
459
462 private:
463
465 };
466 }
467}
468
469#endif
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
void operator()(T1)
the base class for all columnar components
a class representing a single object (electron, muons, etc.)
a class representing a single optional object (electron, muons, etc.)
ContainerFreeAccessor(ColumnarTool< CM > &columnarTool, ColumnAccessorOptions &&options, ColumnAccessorOptionsArray &&optionsArray)
a help implementation of AccessorTemplate that handles type conversions
concept for a container id
VectorConvertView(FunctionType &&, ViewType &&) -> VectorConvertView< std::decay_t< FunctionType >, std::decay_t< ViewType > >
void moveAccessor(unsigned &dataIndex, std::unique_ptr< ColumnAccessorDataArray > &accessorData, unsigned &sourceIndex, std::unique_ptr< ColumnAccessorDataArray > &sourceData)
bool operator==(const ObjectId< CI, ColumnarModeXAOD > &lhs, const ObjectId< CI, ColumnarModeXAOD > &rhs)
Definition ObjectId.h:82
ColumnAccessMode
an enum for the different access modes for a column
Definition ColumnInfo.h:19
@ output
an output column
Definition ColumnInfo.h:24
@ input
an input column
Definition ColumnInfo.h:21
constexpr ColumnarOffsetType invalidObjectIndex
the value for an invalid element index
std::ostream & operator<<(std::ostream &str, const ObjectId< CI, ColumnarModeXAOD > &obj)
Definition ObjectId.h:76
Definition index.py:1
STL namespace.
a struct that contains meta-information about each column that's needed to interface the column with ...
Definition ColumnInfo.h:35
a special column type that behaves like an OptObjectId, but applies an internal cast in xAOD mode
Definition LinkColumn.h:25
a "variant" ContainerId
Definition VariantDef.h:98
typename CIBase::xAODObjectIdType xAODObjectIdType
Definition VariantDef.h:120