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