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 noexcept
67 {
68 return m_link->isValid();
69 }
70
72 [[nodiscard]] bool has_value () const noexcept
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.variantLinkKeyColumn = keysName;
347 dataInfo.linkTargetNames.reserve (VariantCI::numVariants);
348 for (unsigned i = 0; i < VariantCI::numVariants; ++ i)
349 dataInfo.linkTargetNames.emplace_back (containerIdNames[i]);
350 auto keyInfo = options.makeColumnInfo();
351 keyInfo.accessMode = ColumnAccessMode::input;
352 keyInfo.fixedDimensions.push_back (VariantCI::numVariants);
353
354 m_dataData = std::make_unique<ColumnAccessorDataArray> (&m_dataIndex, &m_dataData, &typeid (typename CM::LinkIndexType), CAM);
355 columnarTool.addColumn (dataName, m_dataData.get(), std::move (dataInfo));
356 m_keysData = std::make_unique<ColumnAccessorDataArray> (&m_keysIndex, &m_keysData, &typeid (typename CM::LinkKeyType), ColumnAccessMode::input);
357 columnarTool.addColumn (keysName, m_keysData.get(), std::move (keyInfo));
358 }
359
361 {
362 moveAccessor (m_dataIndex, m_dataData, that.m_dataIndex, that.m_dataData);
363 moveAccessor (m_keysIndex, m_keysData, that.m_keysIndex, that.m_keysData);
364 }
365
367 {
368 if (this != &that)
369 {
370 moveAccessor (m_dataIndex, m_dataData, that.m_dataIndex, that.m_dataData);
371 moveAccessor (m_keysIndex, m_keysData, that.m_keysIndex, that.m_keysData);
372 }
373 return *this;
374 }
375
376 auto operator () (void** dataArea, std::size_t index) const noexcept
377 requires (CAM == ColumnAccessMode::input)
378 {
379 auto *data = static_cast<const typename CM::LinkIndexType*>(dataArea[m_dataIndex]);
380 auto *keys = static_cast<const typename CM::LinkKeyType*>(dataArea[m_keysIndex]);
381 return ObjectLink<VariantContainerId<CIBase,CIList...>,CM> (data[index], keys, dataArea);
382 }
383
384 [[nodiscard]] auto operator () (void** dataArea, std::size_t beginIndex, std::size_t endIndex) const noexcept
385 requires (CAM == ColumnAccessMode::input)
386 {
387 auto *data = static_cast<const typename CM::LinkIndexType*>(dataArea[m_dataIndex]);
388 auto *keys = static_cast<const typename CM::LinkKeyType*>(dataArea[m_keysIndex]);
389 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));
390 }
391
392 template<ContainerIdConcept CI2>
393 requires (CAM == ColumnAccessMode::output && VariantCI::template isValidContainer<CI2>())
394 void set (void** dataArea, std::size_t index, ObjectId<CI2,CM> obj) const noexcept
395 {
396 auto *data = static_cast<typename CM::LinkIndexType*>(dataArea[m_dataIndex]);
397 auto *keys = static_cast<const typename CM::LinkKeyType*>(dataArea[m_keysIndex]);
398 data[index] = CM::mergeLinkKeyIndex (keys[VariantCI::template getVariantIndex<CI2>()], obj.getIndex());
399 }
400
401 [[nodiscard]] bool isAvailable (void** dataArea) const noexcept
402 {
403 auto *data = static_cast<const typename CM::LinkIndexType*>(dataArea[m_dataIndex]);
404 return data != nullptr;
405 }
406
407
408
411 private:
412
413 unsigned m_dataIndex = 0u;
414 std::unique_ptr<ColumnAccessorDataArray> m_dataData;
415 unsigned m_keysIndex = 0u;
416 std::unique_ptr<ColumnAccessorDataArray> m_keysData;
417 };
418
419
420
421 template<ContainerIdConcept CIBase,ContainerIdConcept... CIList,typename ELT>
423 {
426 public:
427
428 using CI = VariantContainerId<CIBase,CIList...>;
432
433 static constexpr bool isDefined = true;
434 static constexpr unsigned internalOffsetColumns = BaseAccessor::internalOffsetColumns;
435
437
438 ContainerFreeAccessor (ColumnarTool<CM>& columnarTool, ColumnAccessorOptions&& options, ColumnAccessorOptionsArray&& optionsArray)
439 : m_accessor (columnarTool, std::move (options), std::move (optionsArray))
440 {}
441
442 auto operator () (void** dataArea, std::size_t index) const noexcept
443 {
444 return m_accessor(dataArea, index).opt_value();
445 }
446
447 auto operator () (void** dataArea, std::size_t beginIndex, std::size_t endIndex) const noexcept
448 {
449 return VectorConvertView ([] (const ObjectLink<CI,CM>& link) {return link.opt_value();},
450 m_accessor(dataArea, beginIndex, endIndex));
451 }
452
453 bool isAvailable (void** dataArea) const noexcept
454 {
455 return m_accessor.isAvailable (dataArea);
456 }
457
460 private:
461
463 };
464 }
465}
466
467#endif
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
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