ATLAS Offline Software
Loading...
Searching...
No Matches
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).
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
34using mutex_t = AthContainers_detail::mutex;
36using guard_t = AthContainers_detail::lock_guard<mutex_t>;
37
38#ifndef XAOD_STANDALONE
39namespace xAODPrivate {
40
43
44 public:
46 HolderBucket(const std::string& key, const std::type_info& ti,
47 xAOD::Event& event)
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.
97 result = m_event.getOutputObject(m_key, tinfo, METADATA);
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
142class 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
151 void setProxy(SG::DataProxy& proxy) { m_proxy = &proxy; }
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
183namespace xAOD {
184
185SG::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;
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
213SG::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
275std::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
290
291 return getHash(str);
292}
293
294const std::string* Event::keyToString(SG::sgkey_t key) const {
295
296 return &(getName(key));
297}
298
299const std::string* Event::keyToString(SG::sgkey_t key, CLID&) const {
300
301 return &(getName(key));
302}
303
304void 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
315const 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;
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 }
394 const Details::IObjectManager* mgr =
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
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
AthContainers_detail::mutex mutex_t
Mutex type for multithread synchronization.
AthContainers_detail::lock_guard< mutex_t > guard_t
Guard type for multithreaded synchronisation.
uint32_t CLID
The Class ID type.
Define macros for attributes used to control the static checker.
#define ATLAS_THREAD_SAFE
void upgrade()
Convert the lock from upgrade to exclusive.
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 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 * cast(CLID, SG::IRegisterTransient *, bool) override
Return the object, cast to a CLID's 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:59
EventFormat m_inputEventFormat
Format of the current input file.
Definition Event.h:321
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:354
AthContainers_detail::upgrading_lock< upgrade_mutex_t > upgrading_lock_t
Lock type for multithread synchronization.
Definition Event.h:351
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:308
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:27
bool m_printEventProxyWarnings
Option to silence common warnings that seem to be harmless.
Definition Event.h:335
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:323
Object_t m_outputObjects
Collection of all the managed output object.
Definition Event.h:313
SG::SGKeyMap< BranchInfo > m_branches ATLAS_THREAD_SAFE
Map from hashed sgkey to BranchInfo.
Definition Event.h:358
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
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:341
std::unique_ptr< SG::DataProxy > m_proxy
Data proxy describing this branch/object.
Definition Event.h:343
const ::TClass * m_class
Dictionary describing this branch/object.
Definition Event.h:345
Threading definitions.