23 const std::map<std::string, std::string, std::less<>> typeMap = {
24 {
"char",
"B" }, {
"unsigned char",
"b" }, {
"short",
"S" }, {
"unsigned short",
"s" },
25 {
"int",
"I" }, {
"unsigned int",
"i" }, {
"float",
"F" }, {
"double",
"D" },
26 {
"long long",
"L" }, {
"unsigned long long",
"l" }, {
"long",
"G" }, {
"unsigned long",
"g" },
30 std::optional<std::string> getLeafListForType(
const std::string_view& typeName ) {
31 auto it = typeMap.find( typeName );
32 return ( it != typeMap.end() ) ? std::optional<std::string>{ it->second } : std::nullopt;
39 const std::string& branchName,
const std::string& location,
const std::string& algName,
40 unsigned int bufferSize,
unsigned int splitLevel )
42 auto leafListTag = getLeafListForType(
m_className );
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 ) );
51 }
else if ( TClass::GetClass(
m_className.c_str() ) ) {
56 setBranchAddress = []( gsl::not_null<TBranch*> br,
const void** wrappedDataPtr ) {
57 br->SetAddress( wrappedDataPtr );
61 throw GaudiException( std::format(
"Cannot create branch {} for unknown class: {}. Provide a dictionary please.",
74 auto* cls = TClass::GetClass(
m_className.c_str() );
75 if ( cls ) cls->Destructor(
const_cast<void*
>(
m_dataBuffer ) );
83 ,
m_branch( std::exchange( other.m_branch,
nullptr ) )
84 ,
m_ownsBuffer( std::exchange( other.m_ownsBuffer,
false ) )
90 if (
this != &other ) {
93 auto* cls = TClass::GetClass(
m_className.c_str() );
94 if ( cls ) cls->Destructor(
const_cast<void*
>(
m_dataBuffer ) );
97 m_branch = std::exchange( other.m_branch,
nullptr );
98 m_ownsBuffer = std::exchange( other.m_ownsBuffer,
false );
119 m_dataBuffer = baseWrapper ? baseWrapper->payload() : pObj.get();
124 unsigned int approxEventsPerBasket,
unsigned int splitLevel ) {
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 };
134 ( fmt::format(
"{}/{}",
m_className, leafListTag.value() ) ).c_str(), minBufferSize );
135 }
else if ( TClass::GetClass(
m_className.c_str() ) ) {
137 dummy_branch = dummy_tree->Branch(
"DummyBranch",
m_className.c_str(), &
m_dataBuffer, minBufferSize, splitLevel );
139 int nWritten = dummy_branch->Fill();
140 if ( nWritten >= 0 ) {
141 unsigned int newBasketSize = nWritten * approxEventsPerBasket;
143 if ( std::numeric_limits<Int_t>::max() / approxEventsPerBasket < (
unsigned int)nWritten ) {
144 newBasketSize = std::numeric_limits<Int_t>::max();
146 return std::min( maxBufferSize, std::max( minBufferSize, newBasketSize ) );
148 return minBufferSize;
153 auto nEvents =
m_branch->GetTree()->GetEntries();
154 auto nEntries =
m_branch->GetEntries();
155 if ( nEntries < nEvents ) {
157 for (
auto i = nEntries; i < nEvents; i++ ) {
m_branch->Fill(); }
Define general base for Gaudi exception.
constexpr static const auto FAILURE
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 entrie...
void(* setBranchAddress)(gsl::not_null< TBranch * >, const void **)
void setDataPtr(void const *dataPtr)
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 & operator=(BranchWrapper &&other) noexcept
void setBranchData(const gsl::not_null< DataObject * > pObj)
void const * m_dataBuffer