ATLAS Offline Software
EventIProxyDict.cxx
Go to the documentation of this file.
1 // Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2 //
3 // File holding the implementation of the xAOD::Event functions that implement
4 // the IProxyDict interface.
5 //
6 
7 // Local include(s).
8 #include "xAODRootAccess/Event.h"
12 
13 // Project include(s).
14 #ifndef XAOD_STANDALONE
16 #include "GaudiKernel/Converter.h"
17 #include "GaudiKernel/GenericAddress.h"
18 #include "SGTools/DataProxy.h"
20 #endif // NOT XAOD_STANDALONE
23 
24 // ROOT include(s):
25 #include <TBranch.h>
26 #include <TClass.h>
27 #include <TString.h>
28 
29 // System include(s):
30 #include <set>
31 #include <stdexcept>
32 
36 using guard_t = AthContainers_detail::lock_guard<mutex_t>;
37 
38 #ifndef XAOD_STANDALONE
39 namespace xAODPrivate {
40 
42 class HolderBucket : public DataBucketBase {
43 
44  public:
46  HolderBucket(const std::string& key, const std::type_info& ti,
48  : m_key(key), m_ti(ti), m_event(event) {}
49 
51  void* object() override {
52 
53  // Look among the output objects first:
54  static constexpr bool METADATA = false;
55  const void* result = m_event.getOutputObject(m_key, m_ti, METADATA);
56  // Check if it succeeded:
57  static constexpr bool SILENT = false;
58  if (!result) {
59  // Try the input then:
60  result = m_event.getInputObject(m_key, m_ti, SILENT, METADATA);
61  } else {
62  // Even if there is an output object with this key, it may
63  // be an input object that was copied to the output. So let's
64  // try to silently retrieve an input object as well. This makes
65  // sure that the input/output object is updated for the current
66  // event.
67  static constexpr bool SILENT = false;
68  m_event.getInputObject(m_key, m_ti, SILENT, METADATA);
69  }
70 
71  // Return the pointer:
72  void* nc_result ATLAS_THREAD_SAFE =
73  const_cast<void*>(result); // DataBucketBase interface
74  return nc_result;
75  }
76 
78  const std::type_info& tinfo() const override { return m_ti; }
79 
81  void* cast(CLID, SG::IRegisterTransient*, bool) override {
82 
83  throw std::runtime_error("xAODPrivate::HolderBucket::cast not implemented");
84  return 0;
85  }
86 
88  void* cast(const std::type_info& tinfo, SG::IRegisterTransient*,
89  bool isConst) override {
90 
91  // Do the cast:
92  static constexpr bool SILENT = true;
93  static constexpr bool METADATA = false;
94  const void* result = nullptr;
95  if (isConst == false) {
96  // Just look among the outputs.
98  } else {
99  // Look among the output objects first:
100  result = m_event.getOutputObject(m_key, tinfo, METADATA);
101  // Check if it succeeded:
102  if (result == nullptr) {
103  // Try the input then:
104  result = m_event.getInputObject(m_key, tinfo, SILENT, METADATA);
105  } else {
106  // Even if there is an output object with this key, it may
107  // be an input object that was copied to the output. So let's
108  // try to silently retrieve an input object as well. This makes
109  // sure that the input/output object is updated for the current
110  // event.
111  m_event.getInputObject(m_key, tinfo, SILENT, METADATA);
112  }
113  }
114 
115  // Return the pointer:
116  void* nc_result ATLAS_THREAD_SAFE =
117  const_cast<void*>(result); // DataBucketBase interface
118  return nc_result;
119  }
120 
122  void* cast(CLID, const std::type_info& tinfo, SG::IRegisterTransient* irt,
123  bool isConst) override {
124  return HolderBucket::cast(tinfo, irt, isConst);
125  }
126 
128  void relinquish() override {}
130  void lock() override {}
131 
132  private:
134  const std::string m_key;
136  const std::type_info& m_ti;
139 
140 }; // class HolderBucket
141 
142 class Loader : public Converter {
143  public:
144  Loader(xAOD::Event& event, const std::string& name, const std::type_info& ti)
145  : Converter(0, CLID_NULL),
146  m_event(event),
147  m_name(name),
148  m_ti(ti),
149  m_proxy(nullptr) {}
150 
152 
153  virtual StatusCode createObj(IOpaqueAddress*, DataObject*& obj) override {
154  static const bool SILENT = true;
155  static const bool METADATA = false;
156 
157  // Try to find the object amongst the output objects first:
158  if (m_event.getOutputObject(m_name, m_ti, METADATA)) {
160  return StatusCode::SUCCESS;
161  }
162  // If it's not on the output, try the input:
163  else if (m_event.getInputObject(m_name, m_ti, SILENT, METADATA)) {
165  m_proxy->setConst();
166  return StatusCode::SUCCESS;
167  }
168 
169  return StatusCode::FAILURE;
170  }
171  virtual long repSvcType() const override { return 0; }
172 
173  private:
175  std::string m_name;
176  const std::type_info& m_ti;
178 }; // class Loader
179 
180 } // namespace xAODPrivate
181 #endif // not XAOD_STANDALONE
182 
183 namespace xAOD {
184 
185 SG::DataProxy* Event::proxy(const void* const pTransient) const {
186 
187  // Look up the name of this object
188  std::string name = getName(pTransient);
189  if (name.empty()) {
190  // Apparently the object is not known...
191  return nullptr;
192  }
193 
194  // Get the metadata object for it:
195  const xAOD::EventFormatElement* efe = 0;
196  static const bool QUIET = true;
197  if (m_outputEventFormat) {
198  efe = m_outputEventFormat->get(name, QUIET);
199  }
200  if (!efe) {
201  efe = m_inputEventFormat.get(name, QUIET);
202  }
203  if (!efe) {
204  // No metadata found...
205  return nullptr;
206  }
207 
208  // Return the proxy:
209  const BranchInfo* bi = getBranchInfo(efe->hash());
210  return bi->m_proxy.get();
211 }
212 
213 SG::DataProxy* Event::proxy(const CLID&, const std::string& key) const {
214 
215  const SG::sgkey_t sgkey = getHash(key);
216  if (!sgkey) {
217  return 0;
218  }
219  return proxy_exact(sgkey);
220 }
221 
223 
224  // Get the object describing this branch/object:
225  const BranchInfo* bi = getBranchInfo(sgkey);
226  if (!bi) {
227  static SG::SGKeySet missingSGKeys ATLAS_THREAD_SAFE;
228  static mutex_t mutex;
229  guard_t lock(mutex);
230  if (missingSGKeys.emplace(sgkey).second && m_printEventProxyWarnings) {
231  ATH_MSG_WARNING("Can't find BranchInfo for: " << sgkey);
232  }
233  return 0;
234  }
235 
236  // Access its data proxy:
237  SG::DataProxy* proxy = bi->m_proxy.get();
238 
239  // Return the proxy:
240  return proxy;
241 }
242 
252 
254 
255  // Warn the user that the function got called:
256  static std::atomic_flag warningPrinted ATLAS_THREAD_SAFE = ATOMIC_FLAG_INIT;
257  if (!warningPrinted.test_and_set() && m_printEventProxyWarnings) {
259  "Function should only be called through an invalid ElementLink");
260  }
261 
262  // Hold on to the proxy with some non-existent, hopefully unique key:
263  const ::TString uniqueKey =
264  ::TString::Format("NonExistentKey_%lu", m_branches.size());
265  BranchInfo bi;
266  bi.m_proxy.reset(proxy);
267  lock.upgrade();
268  m_branches.insert(
269  std::make_pair(stringToKey(uniqueKey.Data(), clid), std::move(bi)));
270 
271  // Return gracefully:
272  return StatusCode::SUCCESS;
273 }
274 
275 std::vector<const SG::DataProxy*> Event::proxies() const {
276 
278 
279  std::vector<const SG::DataProxy*> ret;
280  for (const auto& p : m_branches) {
281  const SG::DataProxy* proxy = p.second.m_proxy.get();
282  if (proxy) {
283  ret.push_back(proxy);
284  }
285  }
286  return ret;
287 }
288 
289 SG::sgkey_t Event::stringToKey(const std::string& str, CLID) {
290 
291  return getHash(str);
292 }
293 
294 const std::string* Event::keyToString(SG::sgkey_t key) const {
295 
296  return &(getName(key));
297 }
298 
299 const std::string* Event::keyToString(SG::sgkey_t key, CLID&) const {
300 
301  return &(getName(key));
302 }
303 
304 void Event::registerKey(SG::sgkey_t, const std::string&, CLID) {
305 
306  return;
307 }
308 
310  const std::string&, bool, bool) {
311 
312  throw std::runtime_error("xAOD::Event::recordObject is not implemented");
313 }
314 
315 const std::string& Event::name() const {
316 
317  static const std::string result{"xAOD::Event"};
318  return result;
319 }
320 
322  SG::sgkey_t sgkey) const {
323 
324  const xAOD::EventFormatElement* efe = nullptr;
325  static const bool QUIET = true;
326  if (m_outputEventFormat) {
327  efe = m_outputEventFormat->get(sgkey, QUIET);
328  }
329  if (!efe) {
330  efe = m_inputEventFormat.get(sgkey, QUIET);
331  }
332  if (!efe) {
333  static SG::SGKeySet missingSGKeys ATLAS_THREAD_SAFE;
334  static mutex_t mutex;
335  guard_t lock(mutex);
336  if (missingSGKeys.emplace(sgkey).second) {
339  "Can't find EventFormatElement for hashed SG key: " << sgkey);
340  }
341  return 0;
342  }
343  }
344  return efe;
345 }
346 
348 
349  {
350  // We can only hold the lock (even though it's a shared lock) for
351  // this limited scope because the call to getInputObject below
352  // leads to a recursion and dead-lock if not released immediately.
354 
355  // If the object already exists, return it:
356  auto it = m_branches.find(sgkey);
357  if (it != m_branches.end()) {
358  return &(it->second);
359  }
360  }
361 
362  // If not, construct it now:
363  BranchInfo bi;
365  if (!efe) {
366  // Apparently this key is not known:
367  return nullptr;
368  }
369 
370  // Helper variable(s).
371  static const bool SILENT = true;
372  static const bool METADATA = false;
373 
374  // The name of the requested object.
375  const std::string& name = getName(sgkey);
376  // This is a bit perverse... In order to let the "base class" figure
377  // out the exact type of this object, we ask for it with an "Event
378  // pointer". I use that type because I need something that has a
379  // dictionary, and which should always be available when this code
380  // runs. In the end it doesn't matter that the object can't be
381  // retrieved as that type (of course...), it only matters that it gets
382  // "set up" following these calls.
383  Event* nc_this = const_cast<Event*>(this);
384  static const std::type_info& dummy = typeid(Event);
385  nc_this->getInputObject(name, dummy, SILENT, METADATA);
386  auto itr = m_outputObjects.find(name);
387  if (itr == m_outputObjects.end()) {
388  itr = m_inputObjects.find(name);
389  if (itr == m_inputObjects.end()) {
390  // We didn't find this object in the store...
391  return nullptr;
392  }
393  }
395  dynamic_cast<const Details::IObjectManager*>(itr->second.get());
396  if (!mgr) {
397  ATH_MSG_ERROR("Internal logic error found");
398  return nullptr;
399  }
400  bi.m_class = mgr->holder()->getClass();
401  // There's no need to check whether this is a "proper" dictionary
402  // at this point, since if TEvent is holding on to it, the type
403  // must have a proper compiled dictionary.
404 
405 #ifndef XAOD_STANDALONE
406  // Create a proper proxy for the input branch:
407  auto taddr = std::make_unique<SG::TransientAddress>(
408  CLID_NULL, efe->branchName(), new GenericAddress());
409  taddr->setSGKey(sgkey);
411  *nc_this, getName(sgkey), *bi.m_class->GetTypeInfo());
412  bi.m_proxy = std::make_unique<SG::DataProxy>(std::move(taddr), loader);
413  loader->setProxy(*bi.m_proxy.get());
414 #endif // not XAOD_STANDALONE
415 
416  // Add the branch info to our list:
418  lock.upgrade();
419  auto ret = m_branches.insert(std::make_pair(sgkey, std::move(bi)));
420 
421  // Return a pointer to the branch info:
422  return &(ret.first->second);
423 }
424 
425 } // namespace xAOD
xAODPrivate::HolderBucket::cast
void * cast(CLID, SG::IRegisterTransient *, bool) override
Return the object, cast to a CLID's type.
Definition: EventIProxyDict.cxx:81
SG::IRegisterTransient
Interface for registering a transient object in t2p map.
Definition: IRegisterTransient.h:28
common.sgkey
def sgkey(tool)
Definition: common.py:1027
xAOD::Event::getEventFormatElement
const xAOD::EventFormatElement * getEventFormatElement(SG::sgkey_t sgkey) const
Get the metadata object for a given "SG key".
Definition: EventIProxyDict.cxx:321
xAOD::EventFormat_v1::get
const EventFormatElement * get(const std::string &key, bool quiet=false) const
Get the description of a given branch.
Definition: EventFormat_v1.cxx:91
xAODPrivate::Loader
Definition: EventIProxyDict.cxx:142
xAOD::Event::ATLAS_THREAD_SAFE
SG::SGKeyMap< BranchInfo > m_branches ATLAS_THREAD_SAFE
Map from hashed sgkey to BranchInfo.
Definition: Event.h:358
get_generator_info.result
result
Definition: get_generator_info.py:21
StateLessPT_NewConfig.proxy
proxy
Definition: StateLessPT_NewConfig.py:407
xAODPrivate::HolderBucket::tinfo
const std::type_info & tinfo() const override
Return the type_info of the stored object.
Definition: EventIProxyDict.cxx:78
xAODPrivate::Loader::Loader
Loader(xAOD::Event &event, const std::string &name, const std::type_info &ti)
Definition: EventIProxyDict.cxx:144
xAOD::Event::name
const std::string & name() const override
Get the name of the instance.
Definition: EventIProxyDict.cxx:315
DataBucketBase
A non-templated base class for DataBucket, allows to access the transient object address as a void*.
Definition: DataBucketBase.h:24
xAOD::Event::BranchInfo::m_class
const ::TClass * m_class
Dictionary describing this branch/object.
Definition: Event.h:345
DataBucketBase.h
xAOD::Event::m_inputObjects
Object_t m_inputObjects
Collection of all the managed input objects.
Definition: Event.h:308
xAODPrivate::HolderBucket::m_event
xAOD::Event & m_event
The original Event object.
Definition: EventIProxyDict.cxx:138
xAOD::Event::m_inputEventFormat
EventFormat m_inputEventFormat
Format of the current input file.
Definition: Event.h:321
BeamSpot::mutex
std::mutex mutex
Definition: InDetBeamSpotVertex.cxx:18
xAOD::Event::recordObject
SG::DataProxy * recordObject(SG::DataObjectSharedPtr< DataObject > obj, const std::string &key, bool allowMods, bool returnExisting) override
Record an object in the store.
Definition: EventIProxyDict.cxx:309
StateLessPT_NewConfig.Format
Format
Definition: StateLessPT_NewConfig.py:149
xAODPrivate::Loader::setProxy
void setProxy(SG::DataProxy &proxy)
Definition: EventIProxyDict.cxx:151
xAOD::Event::Event
Event(std::string_view name)
Constructor with a name.
Definition: EventCore.cxx:27
TRT::Track::event
@ event
Definition: InnerDetector/InDetCalibEvent/TRT_CalibData/TRT_CalibData/TrackInfo.h:74
skel.it
it
Definition: skel.GENtoEVGEN.py:407
xAODPrivate::Loader::m_ti
const std::type_info & m_ti
Definition: EventIProxyDict.cxx:176
xAOD
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
Definition: ICaloAffectedTool.h:24
xAOD::Event::keyToString
const std::string * keyToString(SG::sgkey_t key) const override
Find the string corresponding to a given key.
Definition: EventIProxyDict.cxx:294
xAOD::EventFormatElement
Class describing one branch of the ROOT file.
Definition: EventFormatElement.h:35
xAOD::Event::stringToKey
SG::sgkey_t stringToKey(const std::string &str, CLID clid) override
Find the string corresponding to a given key.
Definition: EventIProxyDict.cxx:289
CxxUtils::RefCountedPtr
Simple smart pointer for Gaudi-style refcounted objects.
Definition: RefCountedPtr.h:39
python.RatesEmulationExample.lock
lock
Definition: RatesEmulationExample.py:148
xAODPrivate::Loader::createObj
virtual StatusCode createObj(IOpaqueAddress *, DataObject *&obj) override
Definition: EventIProxyDict.cxx:153
xAOD::EventFormatElement::branchName
const std::string & branchName() const
Get the branch/key name.
Definition: EventFormatElement.cxx:30
xAODPrivate::HolderBucket::relinquish
void relinquish() override
Give up ownership of the bucket's contents. A no-op.
Definition: EventIProxyDict.cxx:128
xAOD::EventFormatElement::hash
sgkey_t hash() const
Get the hash belonging to this branch/key.
Definition: EventFormatElement.cxx:48
xAODPrivate::HolderBucket::lock
void lock() override
Lock the held object. A no-op.
Definition: EventIProxyDict.cxx:130
xAOD::Event::getName
const std::string & getName(const void *obj) const override
Function returning the key describing a known object.
Definition: EventTVirtualEvent.cxx:64
BchCleanup.mgr
mgr
Definition: BchCleanup.py:294
xAODPrivate::HolderBucket::HolderBucket
HolderBucket(const std::string &key, const std::type_info &ti, xAOD::Event &event)
Constructor with an existing holder.
Definition: EventIProxyDict.cxx:46
xAOD::Event::m_printEventProxyWarnings
bool m_printEventProxyWarnings
Option to silence common warnings that seem to be harmless.
Definition: Event.h:335
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:209
xAOD::Event::addToStore
StatusCode addToStore(CLID id, SG::DataProxy *proxy) override
Add a new proxy to the store.
Definition: EventIProxyDict.cxx:251
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
xAOD::Event::proxies
std::vector< const SG::DataProxy * > proxies() const override
return the list of all current proxies in store
Definition: EventIProxyDict.cxx:275
guard_t
AthContainers_detail::lock_guard< mutex_t > guard_t
Guard type for multithreaded synchronisation.
Definition: EventIProxyDict.cxx:36
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
xAOD::Event::BranchInfo::m_proxy
std::unique_ptr< SG::DataProxy > m_proxy
Data proxy describing this branch/object.
Definition: Event.h:343
Message.h
xAODPrivate::HolderBucket::m_ti
const std::type_info & m_ti
The type info of the object.
Definition: EventIProxyDict.cxx:136
IObjectManager.h
xAOD::Event::m_branchesMutex
upgrade_mutex_t m_branchesMutex
Mutex for multithread synchronization.
Definition: Event.h:354
xAOD::Event::getOutputObject
void * getOutputObject(SG::sgkey_t key, const std::type_info &ti) override
Function for retrieving an output object in a non-template way.
Definition: EventTVirtualEvent.cxx:138
CalibDbCompareRT.dummy
dummy
Definition: CalibDbCompareRT.py:59
xAOD::Event::proxy_exact
SG::DataProxy * proxy_exact(SG::sgkey_t sgkey) const override
Get proxy given a hashed key+clid.
Definition: EventIProxyDict.cxx:222
xAOD::Event::BranchInfo
Helper struct used by the IProxyDict code.
Definition: Event.h:341
Event.h
xAOD::Event::getInputObject
const void * getInputObject(SG::sgkey_t key, const std::type_info &ti, bool silent) override
Function for retrieving an input object in a non-template way.
Definition: EventTVirtualEvent.cxx:162
CLID
uint32_t CLID
The Class ID type.
Definition: Event/xAOD/xAODCore/xAODCore/ClassID_traits.h:47
xAODPrivate::HolderBucket
Helper object for holding something through a THolder.
Definition: EventIProxyDict.cxx:42
xAODPrivate::Loader::m_event
xAOD::Event & m_event
Definition: EventIProxyDict.cxx:174
xAOD::Event::m_outputObjects
Object_t m_outputObjects
Collection of all the managed output object.
Definition: Event.h:313
SG::SGKeySet
std::unordered_set< sgkey_t > SGKeySet
A set of sgkey_t values.
Definition: sgkey_t.h:97
Converter
Definition: Converter.h:27
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
xAODPrivate::HolderBucket::m_key
const std::string m_key
The key of the object.
Definition: EventIProxyDict.cxx:134
SG::sgkey_t
uint32_t sgkey_t
Type used for hashed StoreGate key+CLID pairs.
Definition: sgkey_t.h:32
threading.h
Threading definitions.
xAOD::Event::m_outputEventFormat
EventFormat * m_outputEventFormat
Format of the current output file.
Definition: Event.h:323
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
mutex_t
AthContainers_detail::mutex mutex_t
Mutex type for multithread synchronization.
Definition: EventIProxyDict.cxx:34
TransientAddress.h
SG::DataProxy::setConst
void setConst()
Mark this object as const.
Definition: DataProxy.cxx:205
xAODPrivate
Definition: EventIProxyDict.cxx:39
THolder.h
xAODPrivate::Loader::repSvcType
virtual long repSvcType() const override
Definition: EventIProxyDict.cxx:171
xAOD::Event::proxy
SG::DataProxy * proxy(const void *const pTransient) const override
get proxy for a given data object address in memory
Definition: EventIProxyDict.cxx:185
xAOD::Event::getHash
SG::sgkey_t getHash(const std::string &key) const override
Function returning the hash describing an object name.
Definition: EventTVirtualEvent.cxx:27
AthContainers_detail::upgrading_lock
Lock object for taking out upgradable locks.
Definition: threading.h:177
str
Definition: BTagTrackIpAccessor.cxx:11
ATLAS_THREAD_SAFE
#define ATLAS_THREAD_SAFE
Definition: checker_macros.h:211
xAOD::Event::getBranchInfo
const BranchInfo * getBranchInfo(SG::sgkey_t sgkey) const
Get the object describing one object/branch.
Definition: EventIProxyDict.cxx:347
xAOD::Details::IObjectManager
Manager for EDM objects created by ROOT.
Definition: IObjectManager.h:20
xAOD::Event
Base class for the event (xAOD::TEvent and xAOD::REvent) classes.
Definition: Event.h:59
xAODPrivate::Loader::m_name
std::string m_name
Definition: EventIProxyDict.cxx:175
checker_macros.h
Define macros for attributes used to control the static checker.
python.PyAthena.obj
obj
Definition: PyAthena.py:132
xAODPrivate::HolderBucket::object
void * object() override
Return the object held.
Definition: EventIProxyDict.cxx:51
SG::DataProxy
Definition: DataProxy.h:45
xAODPrivate::HolderBucket::cast
void * cast(const std::type_info &tinfo, SG::IRegisterTransient *, bool isConst) override
Return the object, cast to a certain type.
Definition: EventIProxyDict.cxx:88
xAOD::Event::registerKey
void registerKey(SG::sgkey_t key, const std::string &str, CLID clid) override
Remember an additional mapping from key to string/CLID.
Definition: EventIProxyDict.cxx:304
xAODPrivate::HolderBucket::cast
void * cast(CLID, const std::type_info &tinfo, SG::IRegisterTransient *irt, bool isConst) override
Return the object, cast to type.
Definition: EventIProxyDict.cxx:122
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
DataProxy.h
xAODPrivate::Loader::m_proxy
SG::DataProxy * m_proxy
Definition: EventIProxyDict.cxx:177