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 ATHCONTAINERS_ERROR("RootAuxVectorFactory::copyForOutput",
620 std::string("Cannot apply thinning for ElementLink with non-pointer element: ") +
621 m_vecClass->GetName());
622 }
623}
624
625
639 AuxVectorData& a, size_t aindex,
640 AuxVectorData& b, size_t bindex,
641 size_t n) const
642{
643 if (n == 0) return;
644 void* aptr = a.getDataArray (auxid);
645 void* bptr = &a == &b ? aptr : b.getDataArray (auxid);
646 m_type.swapRange (aptr, aindex, bptr, bindex, n);
647}
648
649
658 AuxVectorData& dst, size_t dst_index,
659 size_t n) const
660{
661 if (n == 0) return;
662 m_type.clearRange (dst.getDataArray (auxid), dst_index, n);
663}
664
665
670{
671 return m_type.getSize();
672}
673
674
678const std::type_info* RootAuxVectorFactory::tiVec() const
679{
680 return m_objClass->GetTypeInfo();
681}
682
683
690{
691 return true;
692}
693
694
700const std::type_info* RootAuxVectorFactory::tiAlloc() const
701{
702 return nullptr;
703}
704
705
710{
711 std::string name = SG::normalizedTypeinfoName (*m_vecClass->GetTypeInfo());
712 CxxUtils::ClassName cn (name);
713 std::string alloc_name;
714 if (cn.ntargs() >= 2) {
715 alloc_name = cn.targ(1).fullName();
716 }
717 else if (cn.ntargs() == 1) {
718 alloc_name = "std::allocator<" + cn.targ(0).fullName();
719 if (alloc_name[alloc_name.size()-1] == '>') alloc_name += " ";
720 alloc_name += ">";
721 }
722 return alloc_name;
723}
724
725
736void RootAuxVectorFactory::toTransient (const EventContext& ctx,
737 RootAuxVector& vec) const
738{
739 if (m_isEL == NONE) {
740 return;
741 }
743 ATHCONTAINERS_ERROR("RootAuxVectorFactory::toTransient",
744 std::string("Cannot call toTransient for ElementLink with non-pointer element: ") +
745 m_vecClass->GetName());
746 return;
747 }
748
749 char* ptr = reinterpret_cast<char*> (vec.toPtr());
750 size_t n = vec.size();
752 size_t eltsz = m_type.getSize();
753
754 if (m_isEL == ELEMENT_LINK) {
755 for (size_t i = 0; i < n; i++) {
756 reinterpret_cast<ElementLinkBase*>(ptr + i*eltsz)->toTransient (pdict);
757 }
758 }
759 else if (m_isEL == ELEMENT_LINK_VECTOR) {
760 for (size_t i = 0; i < n; i++) {
761 std::vector<ElementLinkBase>& v =
762 *reinterpret_cast<std::vector<ElementLinkBase>* > (ptr +i*eltsz);
763 for (ElementLinkBase& el : v) {
764 el.toTransient (pdict);
765 }
766 }
767 }
768 else if (m_isEL == DATA_LINK) {
769 for (size_t i = 0; i < n; i++) {
770 reinterpret_cast<DataLinkBase*>(ptr + i*eltsz)->toTransient (pdict);
771 }
772 }
773 else if (m_isEL == DATA_LINK_VECTOR) {
774 for (size_t i = 0; i < n; i++) {
775 std::vector<DataLinkBase>& v =
776 *reinterpret_cast<std::vector<DataLinkBase>* > (ptr +i*eltsz);
777 for (DataLinkBase& dl : v) {
778 dl.toTransient (pdict);
779 }
780 }
781 }
782}
783
784
785} // namespace SG
Manage lookup of vectors of auxiliary data.
std::vector< size_t > vec
Recursively separate out template arguments in a C++ class name.
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
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