The Gaudi Framework  master (9e5914fb)
Loading...
Searching...
No Matches
Gaudi::details::BranchWrapper Struct Reference

Encapsulates a branch within a ROOT TTree, managing the data and interaction with the TTree. More...

#include </builds/gaudi/Gaudi/GaudiUtils/include/Gaudi/details/BranchWrapper.h>

Collaboration diagram for Gaudi::details::BranchWrapper:

Public Member Functions

 BranchWrapper (const gsl::not_null< TTree * > tree, const std::string &className, const std::string &branchName, const std::string &location, const std::string &algName, unsigned int bufferSize=32000, unsigned int splitLevel=99)
 
 ~BranchWrapper ()
 
 BranchWrapper (BranchWrapper &&other) noexcept
 
BranchWrapperoperator= (BranchWrapper &&other) noexcept
 
 BranchWrapper (const BranchWrapper &)=delete
 
BranchWrapperoperator= (const BranchWrapper &)=delete
 
void setDataPtr (void const *dataPtr)
 
void setBranchData (const gsl::not_null< DataObject * > pObj)
 
const std::string & getLocation () const
 
const std::string & getClassName () const
 
void setBufferSize (unsigned int size)
 
unsigned int computeOptimalBufferSize (unsigned int minBufferSize, unsigned int maxBufferSize, unsigned int approxEventsPerBasket, unsigned int splitLevel)
 compute optimal buffer size to fit given number of element per basket, respecting given min and max
 
void padEntries ()
 pad the number of item in the branch to the one of the Tree in which it leaves by adding empty entries
 

Private Attributes

void const * m_dataBuffer = nullptr
 
TBranch * m_branch = nullptr
 
bool m_ownsBuffer = false
 
std::string m_className
 
std::string m_location
 
void(* setBranchAddress )(gsl::not_null< TBranch * >, const void **)
 

Detailed Description

Encapsulates a branch within a ROOT TTree, managing the data and interaction with the TTree.

Definition at line 25 of file BranchWrapper.h.

Constructor & Destructor Documentation

◆ BranchWrapper() [1/3]

Gaudi::details::BranchWrapper::BranchWrapper ( const gsl::not_null< TTree * > tree,
const std::string & className,
const std::string & branchName,
const std::string & location,
const std::string & algName,
unsigned int bufferSize = 32000,
unsigned int splitLevel = 99 )

Definition at line 38 of file BranchWrapper.cpp.

41 : m_className( className ), m_location( location ) {
42 auto leafListTag = getLeafListForType( m_className );
43 if ( leafListTag ) {
44 // Create a branch for fundamental types using the leaflist
45 m_branch = tree->Branch( branchName.c_str(), &m_dataBuffer,
46 ( std::format( "{}/{}", m_className, leafListTag.value() ) ).c_str(), bufferSize );
47 setBranchAddress = []( gsl::not_null<TBranch*> br, const void** wrappedDataPtr ) {
48 br->SetAddress( const_cast<void*>( *wrappedDataPtr ) );
49 };
50
51 } else if ( TClass::GetClass( m_className.c_str() ) ) {
52 // Create a branch for object types using the classname string
53 m_branch = tree->Branch( branchName.c_str(), m_className.c_str(), &m_dataBuffer, bufferSize, splitLevel );
54 // ROOT auto-allocates an object
55 m_ownsBuffer = m_dataBuffer != nullptr;
56 setBranchAddress = []( gsl::not_null<TBranch*> br, const void** wrappedDataPtr ) {
57 br->SetAddress( wrappedDataPtr );
58 };
59
60 } else {
61 throw GaudiException( std::format( "Cannot create branch {} for unknown class: {}. Provide a dictionary please.",
62 branchName, m_className ),
63 algName, StatusCode::FAILURE );
64 }
65
66 if ( !m_branch ) {
67 throw GaudiException( std::format( "Failed to create branch {} for type {}.", branchName, m_className ), algName,
69 }
70 }
constexpr static const auto FAILURE
Definition StatusCode.h:100
void(* setBranchAddress)(gsl::not_null< TBranch * >, const void **)

◆ ~BranchWrapper()

Gaudi::details::BranchWrapper::~BranchWrapper ( )

Definition at line 72 of file BranchWrapper.cpp.

72 {
73 if ( m_ownsBuffer && m_dataBuffer ) {
74 auto* cls = TClass::GetClass( m_className.c_str() );
75 if ( cls ) cls->Destructor( const_cast<void*>( m_dataBuffer ) );
76 m_dataBuffer = nullptr;
77 m_ownsBuffer = false;
78 }
79 }

◆ BranchWrapper() [2/3]

Gaudi::details::BranchWrapper::BranchWrapper ( BranchWrapper && other)
noexcept

Definition at line 81 of file BranchWrapper.cpp.

82 : m_dataBuffer( other.m_dataBuffer )
83 , m_branch( std::exchange( other.m_branch, nullptr ) )
84 , m_ownsBuffer( std::exchange( other.m_ownsBuffer, false ) )
85 , m_className( std::move( other.m_className ) )
86 , m_location( std::move( other.m_location ) )
87 , setBranchAddress( other.setBranchAddress ) {}

◆ BranchWrapper() [3/3]

Gaudi::details::BranchWrapper::BranchWrapper ( const BranchWrapper & )
delete

Member Function Documentation

◆ computeOptimalBufferSize()

unsigned int Gaudi::details::BranchWrapper::computeOptimalBufferSize ( unsigned int minBufferSize,
unsigned int maxBufferSize,
unsigned int approxEventsPerBasket,
unsigned int splitLevel )

compute optimal buffer size to fit given number of element per basket, respecting given min and max

Definition at line 123 of file BranchWrapper.cpp.

124 {
125 // simply try to write one item in a dummey branch of a dummy tree im memory and measure size
126 auto dummy_file = std::make_unique<TMemFile>( "dummy.root", "CREATE" );
127 auto dummy_tree = std::make_unique<TTree>( "DummyTree", "DummyTree", splitLevel, dummy_file->GetDirectory( "/" ) );
128 auto leafListTag = getLeafListForType( m_className );
129 TBranch* dummy_branch{ nullptr };
130 if ( leafListTag ) {
131 // Create a branch for fundamental types using the leaflist
132 dummy_branch =
133 dummy_tree->Branch( "DummyBranch", &m_dataBuffer,
134 ( fmt::format( "{}/{}", m_className, leafListTag.value() ) ).c_str(), minBufferSize );
135 } else if ( TClass::GetClass( m_className.c_str() ) ) {
136 // Create a branch for object types using the classname string
137 dummy_branch = dummy_tree->Branch( "DummyBranch", m_className.c_str(), &m_dataBuffer, minBufferSize, splitLevel );
138 } // no else as unknown className would have raised an exception at constructor level
139 int nWritten = dummy_branch->Fill();
140 if ( nWritten >= 0 ) {
141 unsigned int newBasketSize = nWritten * approxEventsPerBasket;
142 // Ensure that newBasketSize doesn't wrap around
143 if ( std::numeric_limits<Int_t>::max() / approxEventsPerBasket < (unsigned int)nWritten ) {
144 newBasketSize = std::numeric_limits<Int_t>::max();
145 }
146 return std::min( maxBufferSize, std::max( minBufferSize, newBasketSize ) );
147 }
148 return minBufferSize;
149 }

◆ getClassName()

const std::string & Gaudi::details::BranchWrapper::getClassName ( ) const
inline

Definition at line 50 of file BranchWrapper.h.

50{ return m_className; }

◆ getLocation()

const std::string & Gaudi::details::BranchWrapper::getLocation ( ) const
inline

Definition at line 49 of file BranchWrapper.h.

49{ return m_location; }

◆ operator=() [1/2]

BranchWrapper & Gaudi::details::BranchWrapper::operator= ( BranchWrapper && other)
noexcept

Definition at line 89 of file BranchWrapper.cpp.

89 {
90 if ( this != &other ) {
91 // Clean up current state
92 if ( m_ownsBuffer && m_dataBuffer ) {
93 auto* cls = TClass::GetClass( m_className.c_str() );
94 if ( cls ) cls->Destructor( const_cast<void*>( m_dataBuffer ) );
95 }
96 m_dataBuffer = other.m_dataBuffer;
97 m_branch = std::exchange( other.m_branch, nullptr );
98 m_ownsBuffer = std::exchange( other.m_ownsBuffer, false );
99 m_className = std::move( other.m_className );
100 m_location = std::move( other.m_location );
101 setBranchAddress = other.setBranchAddress;
102 }
103 return *this;
104 }

◆ operator=() [2/2]

BranchWrapper & Gaudi::details::BranchWrapper::operator= ( const BranchWrapper & )
delete

◆ padEntries()

void Gaudi::details::BranchWrapper::padEntries ( )

pad the number of item in the branch to the one of the Tree in which it leaves by adding empty entries

Definition at line 151 of file BranchWrapper.cpp.

151 {
152 if ( !m_branch ) return;
153 auto nEvents = m_branch->GetTree()->GetEntries();
154 auto nEntries = m_branch->GetEntries();
155 if ( nEntries < nEvents ) {
156 m_branch->SetAddress( nullptr );
157 for ( auto i = nEntries; i < nEvents; i++ ) { m_branch->Fill(); }
158 }
159 }

◆ setBranchData()

void Gaudi::details::BranchWrapper::setBranchData ( const gsl::not_null< DataObject * > pObj)

Definition at line 116 of file BranchWrapper.cpp.

116 {
117 auto baseWrapper = dynamic_cast<AnyDataWrapperBase*>( pObj.get() );
118 m_ownsBuffer = false;
119 m_dataBuffer = baseWrapper ? baseWrapper->payload() : pObj.get();
121 }

◆ setBufferSize()

void Gaudi::details::BranchWrapper::setBufferSize ( unsigned int size)
inline

Definition at line 51 of file BranchWrapper.h.

51{ m_branch->SetBasketSize( size ); }

◆ setDataPtr()

void Gaudi::details::BranchWrapper::setDataPtr ( void const * dataPtr)

Definition at line 108 of file BranchWrapper.cpp.

108 {
109 m_ownsBuffer = false;
110 m_dataBuffer = dataPtr;
112 }

Member Data Documentation

◆ m_branch

TBranch* Gaudi::details::BranchWrapper::m_branch = nullptr
private

Definition at line 29 of file BranchWrapper.h.

◆ m_className

std::string Gaudi::details::BranchWrapper::m_className
private

Definition at line 31 of file BranchWrapper.h.

◆ m_dataBuffer

void const* Gaudi::details::BranchWrapper::m_dataBuffer = nullptr
private

Definition at line 28 of file BranchWrapper.h.

◆ m_location

std::string Gaudi::details::BranchWrapper::m_location
private

Definition at line 32 of file BranchWrapper.h.

◆ m_ownsBuffer

bool Gaudi::details::BranchWrapper::m_ownsBuffer = false
private

Definition at line 30 of file BranchWrapper.h.

◆ setBranchAddress

void(* Gaudi::details::BranchWrapper::setBranchAddress) (gsl::not_null< TBranch * >, const void **)
private

Definition at line 33 of file BranchWrapper.h.


The documentation for this struct was generated from the following files: