ATLAS Offline Software
Loading...
Searching...
No Matches
RootAuxVectorFactory.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
11
12
17#include "AthLinks/ElementLinkBase.h"
18#include "AthLinks/DataLinkBase.h"
20#include "CxxUtils/ClassName.h"
22#include "TClass.h"
23#include "TVirtualCollectionProxy.h"
24#include "TROOT.h"
25#include <iostream>
26#include <stdexcept>
27
28
29namespace {
30
31
40TClass* lookupVectorType (TClass *cl)
41{
42 std::string tname = cl->GetName();
43 tname += "::vector_type";
44 TDataType* typ = gROOT->GetType (tname.c_str());
45 if (typ)
46 return TClass::GetClass (typ->GetFullTypeName());
47 return nullptr;
48}
49
50
51} // anonymous namespace
52
53
54namespace SG {
55
56
67 size_t size, size_t /*capacity*/,
68 bool isLinked)
70 m_factory (factory),
71 m_ownFlag (true)
72{
73 const TClass* vecClass = factory->vecClass();
74 m_proxy.reset (vecClass->GetCollectionProxy()->Generate());
75 m_obj = factory->objClass()->New ();
76 m_vec = reinterpret_cast<char*> (m_obj) + factory->offset();
77 m_proxy->PushProxy (m_vec);
78 this->resize (size);
79}
80
81
99 void* data,
100 bool isPacked,
101 bool ownFlag,
102 bool isLinked)
104 m_factory (factory),
105 m_ownFlag (ownFlag)
106{
107 if (isPacked) std::abort();
108 const TClass* vecClass = factory->vecClass();
109 m_proxy.reset (vecClass->GetCollectionProxy()->Generate());
110 m_obj = data;
111 m_vec = reinterpret_cast<char*> (m_obj) + factory->offset();
112 m_proxy->PushProxy (m_vec);
113}
114
115
121 : IAuxTypeVector (other),
122 m_factory (other.m_factory),
123 m_proxy (other.m_proxy->Generate()),
124 m_ownFlag (true)
125{
126 m_obj = m_factory->objClass()->New ();
127 m_vec = reinterpret_cast<char*> (m_obj) + m_factory->offset();
128 m_proxy->PushProxy (m_vec);
129 size_t sz = other.size();
130 this->resize (sz);
131
132 if (sz > 0) {
133 const RootUtils::Type& rootType = m_factory->rootType();
134 const void* otherPtr = other.toPtr();
135 rootType.copyRange (this->toPtr(), otherPtr, sz);
136 }
137}
138
139
146{
147 if (m_ownFlag)
148 m_factory->objClass()->Destructor (m_obj);
149}
150
151
155std::unique_ptr<SG::IAuxTypeVector> RootAuxVector::clone() const
156{
157 return std::make_unique<RootAuxVector> (*this);
158}
159
160
165{
166 if (m_proxy->Size() == 0)
167 return 0;
168 return m_proxy->At(0);
169}
170
171
175const void* RootAuxVector::toPtr () const
176{
177 if (m_proxy->Size() == 0)
178 return 0;
179 TVirtualCollectionProxy* proxy ATLAS_THREAD_SAFE = m_proxy.get();
180 return proxy->At(0);
181}
182
183
188{
189 return m_obj;
190}
191
192
197{
198 return m_proxy->Size();
199}
200
201
209{
210 const void* orig = this->getDataSpan().beg;
211 m_proxy->Allocate(sz, false);
212 this->storeDataSpan();
213 return this->getDataSpan().beg == orig;
214}
215
216
221void RootAuxVector::reserve (size_t /*sz*/)
222{
223}
224
225
252bool RootAuxVector::shift (size_t pos, ptrdiff_t offs)
253{
254 size_t eltsz = m_proxy->GetIncrement();
255
256 const RootUtils::Type& rootType = m_factory->rootType();
257
258 if (offs < 0) {
259 if (-offs > static_cast<ptrdiff_t>(pos)) offs = -pos;
260 char* beg = reinterpret_cast<char*>(m_proxy->At(0));
261 rootType.copyRange (beg + eltsz*(pos+offs),
262 beg + eltsz*pos,
263 m_proxy->Size() - pos);
264 m_proxy->Allocate (m_proxy->Size() + offs, false);
265 this->storeDataSpan();
266 return true;
267 }
268 else if (offs > 0) {
269 size_t oldsz = m_proxy->Size();
270 m_proxy->Allocate (oldsz + offs, false);
271 char* beg = reinterpret_cast<char*>(m_proxy->At(0));
272 if (pos < oldsz)
273 rootType.copyRange (beg + eltsz*(pos+offs),
274 beg + eltsz*pos,
275 oldsz - pos);
276 rootType.clearRange (beg + eltsz*pos, offs);
277 this->storeDataSpan();
278 return false;
279 }
280 return true;
281}
282
283
303 void* src, size_t src_pos, size_t src_n,
304 SG::IAuxStore& /*srcStore*/)
305{
306 size_t eltsz = m_proxy->GetIncrement();
307 const void* orig = this->getDataSpan().beg;
308 const RootUtils::Type& rootType = m_factory->rootType();
309
310 char* srcp = reinterpret_cast<char*> (src);
311 char* begp = srcp + src_pos*eltsz;
312
313 shift (pos, src_n);
314 // FIXME: want move, not copy.
315 // But i don't seem to be able to call move operations through cling,
316 // so just use copy for now.
317 rootType.copyRange (reinterpret_cast<char*>(this->toPtr()) + pos*eltsz,
318 begp, src_n);
319 this->storeDataSpan();
320 return this->getDataSpan().beg == orig;
321}
322
323
335const std::type_info* RootAuxVector::objType() const
336{
337 return m_factory->objClass()->GetTypeInfo();
338}
339
340
350void RootAuxVector::toTransient (const EventContext& ctx)
351{
352 m_factory->toTransient (ctx, *this);
353}
354
355
362{
363 void* ptr ATLAS_THREAD_SAFE = const_cast<void*>(this->toPtr());
364 return AuxDataSpanBase (ptr, m_proxy->Size());
365}
366
367
375
376
377//==================================================================
378
379
385 : m_objClass (objClass),
386 m_vecClass (objClass),
387 m_offset (0),
388 m_isEL (NONE)
389{
390 TVirtualCollectionProxy* proxy = m_vecClass->GetCollectionProxy();
391
392 if (!proxy) {
393 TClass* vecClass = lookupVectorType (objClass);
394 if (vecClass) {
395 m_vecClass = vecClass;
396 Int_t offs = objClass->GetBaseClassOffset (vecClass);
397 if (offs >= 0) {
398 m_offset = offs;
399 proxy = vecClass->GetCollectionProxy();
400 }
401 else {
402 ATHCONTAINERS_ERROR("RootAuxVectorFactory::RootAuxVectorFactory",
403 std::string("Can't find vector base class in ") +
404 objClass->GetName());
405 }
406 }
407 }
408
409 if (!proxy) {
410 std::string err = "Can't find collection proxy for ";
411 err += m_vecClass->GetName();
412 throw std::runtime_error (err.c_str());
413 }
414
415 if (m_vecClass->GetTypeInfo() == 0) {
416 ATHCONTAINERS_ERROR("RootAuxVectorFactory::RootAuxVectorFactory",
417 std::string("No type_info available for class ") +
418 m_vecClass->GetName() +
419 std::string(". There is probably a missing dictionary. We will likely crash further on."));
420 }
421
422 TClass* eltClass = proxy->GetValueClass();
423 if (eltClass) {
424 m_type.init (eltClass);
425
426 const std::type_info* ti = eltClass->GetTypeInfo();
427 if (ti) {
428
429 static const CxxUtils::ClassName pat1 ("ElementLink<$T>");
430 static const CxxUtils::ClassName pat2 ("std::vector<ElementLink<$T> >");
431 static const CxxUtils::ClassName pat3 ("DataLink<$T>");
432 static const CxxUtils::ClassName pat4 ("std::vector<DataLink<$T> >");
433
435 CxxUtils::ClassName::match_t matches;
436 if (clname.match (pat1, matches)) {
438 if (eltClass->GetBaseClass ("ElementLinkBase") == nullptr) {
440 }
441 }
442 else if (clname.match (pat2, matches)) {
444
445 TVirtualCollectionProxy* proxy2 = eltClass->GetCollectionProxy();
446 if (proxy2) {
447 TClass* innerEltClass = proxy2->GetValueClass();
448 if (innerEltClass) {
449 if (innerEltClass->GetBaseClass ("ElementLinkBase") == nullptr) {
451 }
452 }
453 }
454 }
455 else if (clname.match (pat3, matches)) {
457 }
458 else if (clname.match (pat4, matches)) {
460 }
461 }
462 }
463 else
464 m_type.init (proxy->GetType());
465}
466
467
474
475
483std::unique_ptr<SG::IAuxTypeVector>
485 size_t size,
486 size_t capacity,
487 bool isLinked) const
488{
489 return std::make_unique<RootAuxVector> (this, auxid, size, capacity,
490 isLinked);
491}
492
493
514std::unique_ptr<SG::IAuxTypeVector>
516 void* data,
518 bool isPacked,
519 bool ownFlag,
520 bool isLinked) const
521{
522 if (linkedVector) std::abort();
523 return std::make_unique<RootAuxVector> (this, auxid, data, isPacked, ownFlag,
524 isLinked);
525}
526
527
531 AuxVectorData& dst,
532 size_t dst_index,
533 const AuxVectorData& src,
534 size_t src_index,
535 size_t n) const
536{
537 if (n == 0) return nullptr;
538 size_t eltsz = m_type.getSize();
539 char* dstptr = reinterpret_cast<char*> (dst.getDataArray (auxid));
540 if (&src == &dst) {
541 // Source and destination containers are the same,
542 // so we don't need to bother with fetching the src pointer.
543 // copyRange properly handles overlapping regions.
544 m_type.copyRange (dstptr + eltsz*dst_index, dstptr + eltsz*src_index, n);
545 return dstptr + eltsz*dst_index;
546 }
547 else {
548 const char* srcptr = reinterpret_cast<const char*>(src.getDataArrayAllowMissing (auxid));
549 if (srcptr) {
550 m_type.copyRange (dstptr + eltsz*dst_index, srcptr + eltsz*src_index, n);
551 return dstptr + eltsz*dst_index;
552 }
553 else {
554 m_type.clearRange (dstptr + eltsz*dst_index, n);
555 return nullptr;
556 }
557 }
558}
559
560
573 AuxVectorData& dst,
574 size_t dst_index,
575 const AuxVectorData& src,
576 size_t src_index,
577 size_t n) const
578{
579 (void)copyImpl (auxid, dst, dst_index, src, src_index, n);
580}
581
582
596 AuxVectorData& dst, size_t dst_index,
597 const AuxVectorData& src, size_t src_index,
598 size_t n) const
599{
600 char* dstptr = copyImpl (auxid, dst, dst_index, src, src_index, n);
601
602 if (m_isEL == ELEMENT_LINK) {
603 size_t eltsz = m_type.getSize();
604 for (size_t i = 0; i < n; i++) {
605 reinterpret_cast<ElementLinkBase*>(dstptr + i*eltsz)->thin();
606 }
607 }
608 else if (m_isEL == ELEMENT_LINK_VECTOR) {
609 size_t eltsz = m_type.getSize();
610 for (size_t i = 0; i < n; i++) {
611 std::vector<ElementLinkBase>& v =
612 *reinterpret_cast<std::vector<ElementLinkBase>* > (dstptr +i*eltsz);
613 for (ElementLinkBase& el : v) {
614 el.thin();
615 }
616 }
617 }
618 else if (m_isEL == ELEMENT_LINK_NONPOINTER) {
619 TVirtualCollectionProxy* proxy = m_vecClass->GetCollectionProxy();
620 TClass* eltClass = proxy->GetValueClass();
621 ATHCONTAINERS_ERROR("RootAuxVectorFactory::copyForOutput",
622 std::format("Tried to copy an auxiliary variable of type {}. However, the target type is not a DataVector and does not have a pointer value type. Such types are only fully supported for fully specified Factory objects, not for this dynamic factory using ROOT reflection information. Perhaps you are trying to write this type by mistake. Otherwise, try creating a SG::Accessor object for this type during event processing to ensure a proper Factory is available.",
623 eltClass->GetName()));
624 }
625}
626
627
641 AuxVectorData& a, size_t aindex,
642 AuxVectorData& b, size_t bindex,
643 size_t n) const
644{
645 if (n == 0) return;
646 void* aptr = a.getDataArray (auxid);
647 void* bptr = &a == &b ? aptr : b.getDataArray (auxid);
648 m_type.swapRange (aptr, aindex, bptr, bindex, n);
649}
650
651
660 AuxVectorData& dst, size_t dst_index,
661 size_t n) const
662{
663 if (n == 0) return;
664 m_type.clearRange (dst.getDataArray (auxid), dst_index, n);
665}
666
667
672{
673 return m_type.getSize();
674}
675
676
680const std::type_info* RootAuxVectorFactory::tiVec() const
681{
682 return m_objClass->GetTypeInfo();
683}
684
685
692{
693 return true;
694}
695
696
702const std::type_info* RootAuxVectorFactory::tiAlloc() const
703{
704 return nullptr;
705}
706
707
712{
713 std::string name = SG::normalizedTypeinfoName (*m_vecClass->GetTypeInfo());
714 CxxUtils::ClassName cn (name);
715 std::string alloc_name;
716 if (cn.ntargs() >= 2) {
717 alloc_name = cn.targ(1).fullName();
718 }
719 else if (cn.ntargs() == 1) {
720 alloc_name = "std::allocator<" + cn.targ(0).fullName();
721 if (alloc_name[alloc_name.size()-1] == '>') alloc_name += " ";
722 alloc_name += ">";
723 }
724 return alloc_name;
725}
726
727
738void RootAuxVectorFactory::toTransient (const EventContext& ctx,
739 RootAuxVector& vec) const
740{
741 if (m_isEL == NONE) {
742 return;
743 }
745 ATHCONTAINERS_ERROR("RootAuxVectorFactory::toTransient",
746 std::string("Cannot call toTransient for ElementLink with non-pointer element: ") +
747 m_vecClass->GetName());
748 return;
749 }
750
751 char* ptr = reinterpret_cast<char*> (vec.toPtr());
752 size_t n = vec.size();
754 size_t eltsz = m_type.getSize();
755
756 if (m_isEL == ELEMENT_LINK) {
757 for (size_t i = 0; i < n; i++) {
758 reinterpret_cast<ElementLinkBase*>(ptr + i*eltsz)->toTransient (pdict);
759 }
760 }
761 else if (m_isEL == ELEMENT_LINK_VECTOR) {
762 for (size_t i = 0; i < n; i++) {
763 std::vector<ElementLinkBase>& v =
764 *reinterpret_cast<std::vector<ElementLinkBase>* > (ptr +i*eltsz);
765 for (ElementLinkBase& el : v) {
766 el.toTransient (pdict);
767 }
768 }
769 }
770 else if (m_isEL == DATA_LINK) {
771 for (size_t i = 0; i < n; i++) {
772 reinterpret_cast<DataLinkBase*>(ptr + i*eltsz)->toTransient (pdict);
773 }
774 }
775 else if (m_isEL == DATA_LINK_VECTOR) {
776 for (size_t i = 0; i < n; i++) {
777 std::vector<DataLinkBase>& v =
778 *reinterpret_cast<std::vector<DataLinkBase>* > (ptr +i*eltsz);
779 for (DataLinkBase& dl : v) {
780 dl.toTransient (pdict);
781 }
782 }
783 }
784}
785
786
787} // namespace SG
Manage lookup of vectors of auxiliary data.
std::vector< size_t > vec
Recursively separate out template arguments in a C++ class name.
static Double_t sz
static Double_t a
Dynamic implementation of IAuxVectorFactory, relying on root's vector proxy.
if(pathvar)
Define macros for attributes used to control the static checker.
#define ATLAS_THREAD_SAFE
Type-independent part of DataLink; holds the persistent state.
Base class for ElementLinks to vectors of pointers.
Wrapper for ROOT types.
Definition Type.h:40
Manage lookup of vectors of auxiliary data.
const void * getDataArray(SG::auxid_t auxid) const
Return a const pointer to the start of an aux data vector.
Interface for non-const operations on an auxiliary store.
Definition IAuxStore.h:51
Abstract interface for manipulating vectors of arbitrary types.
bool isLinked() const
Return true if this variable is linked from another one.
auxid_t auxid() const
Return the auxid of the variable this vector represents.
void storeDataSpan(void *beg, size_t size)
Update the stored span.
const AuxDataSpanBase & getDataSpan() const
Return a reference to a description of this vector's start+size.
IAuxTypeVector(auxid_t auxid, bool isLinked)
Constructor.
Dynamic implementation of IAuxVectorFactory, relying on root's vector proxy.
RootAuxVectorFactory(TClass *objClass)
Constructor.
size_t offset() const
Return the offset of the vector within the object.
virtual void copy(SG::auxid_t auxid, AuxVectorData &dst, size_t dst_index, const AuxVectorData &src, size_t src_index, size_t n) const override
Copy elements between vectors.
virtual bool isDynamic() const override
True if the vectors created by this factory work by dynamic emulation (via TVirtualCollectionProxy or...
virtual ~RootAuxVectorFactory() override
Destructor.
virtual void swap(SG::auxid_t auxid, AuxVectorData &a, size_t aindex, AuxVectorData &b, size_t bindex, size_t n) const override
Swap elements between vectors.
RootUtils::Type m_type
Wrapper for the ROOT type of the element.
char * copyImpl(SG::auxid_t auxid, AuxVectorData &dst, size_t dst_index, const AuxVectorData &src, size_t src_index, size_t n) const
Helper for copy; returns a pointer to the first destination object, or nullptr if the destination was...
virtual const std::type_info * tiVec() const override
Return the type_info of the overall object.
size_t m_offset
Offset of the STL vector within the overall object.
enum SG::RootAuxVectorFactory::@071257101107162132204103261125230107154016006205 m_isEL
Flag to tell whether we need to do thinning / toTrasnsient.
virtual const std::type_info * tiAlloc() const override
Return the type_info of the vector allocator.
virtual std::string tiAllocName() const override
Return the (demangled) name of the vector allocator.
TClass * m_objClass
The TClass for the overall object.
TClass * m_vecClass
The TClass for the std::vector.
void toTransient(const EventContext &ctx, RootAuxVector &vec) const
Perform post-read processing for one variable.
virtual void copyForOutput(SG::auxid_t auxid, AuxVectorData &dst, size_t dst_index, const AuxVectorData &src, size_t src_index, size_t n) const override
Copy elements between vectors, possibly applying thinning.
virtual std::unique_ptr< SG::IAuxTypeVector > createFromData(SG::auxid_t auxid, void *data, IAuxTypeVector *linkedVector, bool isPacked, bool ownFlag, bool isLinked) const override
Create a vector object of this type from a data blob.
virtual std::unique_ptr< SG::IAuxTypeVector > create(SG::auxid_t auxid, size_t size, size_t capacity, bool isLinked) const override
Create a vector object of this type.
virtual size_t getEltSize() const override
Return the size of an element of this vector type.
virtual void clear(SG::auxid_t auxid, AuxVectorData &dst, size_t dst_index, size_t n) const override
Clear a range of elements within a vector.
Dynamic implementation of IAuxTypeVector, relying on root vector proxy.
const RootAuxVectorFactory * m_factory
Pointer back to the factory class for this type.
virtual void toTransient(const EventContext &ctx) override
Perform post-read processing on this auxiliary variable.
void * m_vec
Pointer to the vector object itself.
virtual void * toPtr() override
Return a pointer to the start of the vector's data.
std::unique_ptr< TVirtualCollectionProxy > m_proxy
The collection proxy for the vector.
bool m_ownFlag
Should be delete the vector object?
RootAuxVector(const RootAuxVectorFactory *factory, SG::auxid_t auxid, size_t size, size_t capacity, bool isLinked)
Constructor.
virtual AuxDataSpanBase getDataSpanImpl() const override final
Return a span object describing the current vector.
virtual std::unique_ptr< SG::IAuxTypeVector > clone() const override
Make a copy of this vector.
virtual void * toVector() override
Return a pointer to the overall object.
virtual bool insertMove(size_t pos, void *src, size_t src_pos, size_t src_n, SG::IAuxStore &srcStore) override
Insert elements into the vector via move semantics.
void storeDataSpan()
Update the stored span.
virtual ~RootAuxVector() override
Destructor.
void * m_obj
Pointer to the overall object itself.
virtual bool resize(size_t sz) override
Change the size of the vector.
virtual bool shift(size_t pos, ptrdiff_t offs) override
Shift the elements of the vector.
virtual const std::type_info * objType() const override
Return the type of the complete object to be saved.
virtual void reserve(size_t sz) override
Change the capacity of the vector.
virtual size_t size() const override
Return the size of the vector.
Helper for emitting error messages.
#define ATHCONTAINERS_ERROR(ctx, msg)
Definition error.h:54
IProxyDict * proxyDictFromEventContext()
Return the IProxyDict for this thread's current context.
ClassName()
Default constructor.
Forward declaration.
std::string normalizedTypeinfoName(const std::type_info &info)
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
SG::auxid_t auxid() const
Return the aux id for this variable.
virtual IAuxTypeVector * linkedVector(SG::auxid_t auxid) override
Return interface for a linked variable.
virtual size_t size() const override
Return the number of elements in the store.
size_t auxid_t
Identifier for a particular aux data item.
Definition AuxTypes.h:27
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
TClass * lookupVectorType(TClass &cl)
Internal function used by xAOD::TAuxStore and xAOD::RAuxStore.
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
Some out-of-line helpers for ExtendedEventContext.
Minimal span-like object describing the range of an auxiliary variable.
Definition AuxDataSpan.h:40
void * beg
Pointer to the start of the variable's vector.
Definition AuxDataSpan.h:54