ATLAS Offline Software
Loading...
Searching...
No Matches
THolder.cxx
Go to the documentation of this file.
1// Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2
3// ROOT include(s):
4#include <TClass.h>
5#include <TError.h>
6
7// Athena include(s):
12
13// Local include(s):
17#include "THolderCache.h"
18
19namespace {
20
22 xAOD::THolder::TypeKind getTypeKind( const TClass* type ) {
23
24 static const TClass* const dvClass =
25 TClass::GetClass( typeid( SG::AuxVectorBase ) );
26 static const TClass* const aeClass =
27 TClass::GetClass( typeid( SG::AuxElement ) );
28
29 // Don't waste time (and possibly invoke autoparsing) for types
30 // that we know can't satisfy the tests below. An AuxElement
31 // should have type kNotSTL, while a DataVector will have
32 // type kSTLlist, by virtue of a setting in TDVCollectionProxy.
33 if( type && (type->GetCollectionType() == ROOT::kNotSTL || type->GetCollectionType() == ROOT::kSTLlist) ) {
34 if( type->InheritsFrom( dvClass ) ) {
36 }
37 if( type->InheritsFrom( aeClass ) ) {
39 }
40 }
42 }
43
45 void* safe_const_cast(const void* object) {
46 void* nc ATLAS_THREAD_SAFE = const_cast<void*>(object);
47 return nc;
48 }
49
50} // private namespace
51
52namespace xAOD {
53
55 : m_object( 0 ), m_type( 0 ), m_typeInfo( 0 ), m_owner( kFALSE ),
56 m_typeKind( OTHER ), m_const( kFALSE ) {
57
58 }
59
60 THolder::THolder( void* object, ::TClass* type, ::Bool_t owner )
61 : m_object( object ), m_type( type ),
62 m_typeInfo( m_type ? m_type->GetTypeInfo() : 0 ), m_owner( owner ),
63 m_typeKind( getTypeKind( type ) ), m_const( kFALSE ) {
64
65 // Complain if the passed dictionary will be unusable later on:
66 if( m_type && ( ! m_type->IsLoaded() ) ) {
67 ::Warning( "xAOD::THolder::THolder", "Received an emulated dictionary "
68 "for type: %s", m_type->GetName() );
69 }
70
71 // Increase the object count:
72 if( m_object && m_owner ) {
73 Internal::THolderCache::instance().incRef( m_object );
74 }
75 }
76
77 THolder::THolder( void* object, const std::type_info& type, ::Bool_t owner )
78 : m_object( object ), m_type( 0 ), m_typeInfo( &type ), m_owner( owner ),
79 m_typeKind( OTHER ), m_const( kFALSE ) {
80
81 // Increase the object count:
82 if( m_object && m_owner ) {
84 }
85 }
86
87 THolder::THolder( const void* object, ::TClass* type, ::Bool_t owner )
88 : THolder( safe_const_cast(object), type, owner ) {
89
90 m_const = kTRUE;
91 }
92
93 THolder::THolder( const void* object, const std::type_info& type, ::Bool_t owner )
94 : THolder( safe_const_cast(object), type, owner ) {
95
96 m_const = kTRUE;
97 }
98
105 THolder::THolder( const THolder& parent )
106 : m_object( parent.m_object ), m_type( parent.m_type ),
107 m_typeInfo( parent.m_typeInfo ), m_owner( parent.m_owner ),
108 m_typeKind( parent.m_typeKind ), m_const( parent.m_const ) {
109
110 // Increase the object count:
111 if( m_object && m_owner ) {
113 }
114 }
115
127 : m_object( parent.m_object ), m_type( parent.m_type ),
128 m_typeInfo( parent.m_typeInfo ), m_owner( parent.m_owner ),
129 m_typeKind( parent.m_typeKind ), m_const( parent.m_const ) {
130
131 // Tell the parent that it no longer owns the object:
132 parent.m_owner = kFALSE;
133 }
134
135 //coverity[UNCAUGHT_EXCEPT]
137
138 // Delete the object using its dictionary:
139 if( m_object && m_owner &&
140 ( ! Internal::THolderCache::instance().decRef( m_object ) ) ) {
141 deleteObject();
142 }
143 }
144
152
153 // Check if we need to do anything:
154 if( &rhs == this ) return *this;
155
156 // Clean up the previously managed object:
157 if( m_object && m_owner &&
158 ( ! Internal::THolderCache::instance().decRef( m_object ) ) ) {
159 deleteObject();
160 }
161
162 // Do the copy:
163 m_object = rhs.m_object;
164 m_type = rhs.m_type;
166 m_owner = rhs.m_owner;
168 m_const = rhs.m_const;
169
170 // Increase the object count:
171 if( m_object && m_owner ) {
173 }
174
175 // Return this same object:
176 return *this;
177 }
178
189
190 // Check if we need to do anything:
191 if( &rhs == this ) return *this;
192
193 // Clean up the previously managed object:
194 if( m_object && m_owner &&
195 ( ! Internal::THolderCache::instance().decRef( m_object ) ) ) {
196 deleteObject();
197 }
198
199 // Do the copy:
200 m_object = rhs.m_object;
201 m_type = rhs.m_type;
202 m_typeInfo = rhs.m_typeInfo;
203 m_owner = rhs.m_owner;
204 m_typeKind = rhs.m_typeKind;
205 m_const = rhs.m_const;
206
207 // Instead of doing anything with the shared count here, just make the
208 // parent not own the object anymore. The logic is the same as discussed
209 // in the move constructor.
210 rhs.m_owner = kFALSE;
211
212 // Return this same object:
213 return *this;
214 }
215
216 const void* THolder::get() const {
217
218 return m_object;
219 }
220
221 void* THolder::get() {
222
223 return m_object;
224 }
225
227
228 return &m_object;
229 }
230
231 void THolder::set( void* obj ) {
232
233 // Check if we need to do anything:
234 if( m_object == obj ) return;
235
236 // Delete the previous object:
237 if( m_object && m_owner &&
238 ( ! Internal::THolderCache::instance().decRef( m_object ) ) ) {
239 deleteObject();
240 }
241
242 // Hold on to the new object from now on:
243 m_object = obj;
244
245 // Increase the object count:
246 if( m_object && m_owner ) {
248 }
249
250 return;
251 }
252
253 ::Bool_t THolder::isOwner() const {
254
255 return m_owner;
256 }
257
258 void THolder::setOwner( ::Bool_t state ) {
259
260 // Check if anything needs to be done:
261 if( state == m_owner ) return;
262
263 if( m_object && m_owner &&
264 ( ! Internal::THolderCache::instance().decRef( m_object ) ) ) {
265 ::Warning( "xAOD::THolder::setOwner",
266 "Deleting object %p no longer held by any owner",
267 m_object );
268 deleteObject();
269 }
270
271 m_owner = state;
272
273 if( m_object && m_owner ) {
275 }
276
277 return;
278 }
279
280 ::Bool_t THolder::isConst() const {
281
282 return m_const;
283 }
284
286
287 m_const = kTRUE;
288 }
289
297 void* THolder::getImpl( const std::type_info& tid,
298 ::Bool_t silent ) const {
299
300 // If there is no dictionary for the object, then the logic is pretty
301 // simple:
302 if( ! m_type ) {
303 // Check if the user asked for the right type. Remember that in this
304 // case we can't return an object as its base type.
305 if( tid != *m_typeInfo ) {
306 if( ! silent ) {
307 const std::string heldType =
309 const std::string reqType =
311 ::Warning( "xAOD::THolder::getAs",
312 "Trying to retrieve %s object with a %s pointer",
313 heldType.c_str(), reqType.c_str() );
314 }
315 return 0;
316 }
317 // The user did ask for the correct type:
318 return m_object;
319 }
320
321 // Check if we already know about this type:
322 auto userClass = Internal::THolderCache::instance().getClass( tid );
323 // If not, look for it now:
324 if( ! userClass.first ) {
325 userClass.second = ::TClass::GetClass( tid );
326 Internal::THolderCache::instance().addClass( tid, userClass.second );
327 }
328
329 // If we still don't have a dictionary, that's an issue:
330 if( ! userClass.second ) {
331 if( ! silent ) {
332 ::Error( "xAOD::THolder::getAs",
333 XAOD_MESSAGE( "Couldn't access the dictionary for user "
334 "type: %s" ),
335 SG::normalizedTypeinfoName( tid ).c_str() );
336 }
337 return 0;
338 }
339
340 // Check if the user requested a valid base class for the held type.
341 //
342 // Calling GetBaseClassOffset is in general not thread-safe as it could
343 // trigger the loading and parsing of StreamerInfo. However, we assume
344 // that this has already been done once we get here.
345 TClass* cl ATLAS_THREAD_SAFE = m_type;
346 const Int_t offset = cl->GetBaseClassOffset( userClass.second );
347 if( offset < 0 ) {
348 if( ! silent ) {
349 ::Warning( "xAOD::THolder::getAs",
350 "User class \"%s\" is not a valid base "
351 "of \"%s\"",
352 SG::normalizedTypeinfoName( tid ).c_str(),
353 m_type->GetName() );
354 }
355 return 0;
356 }
357
358 // If all is fine, do the cast:
359 return ( static_cast< char* >( m_object ) + offset );
360 }
361
371 void* THolder::getAs( const std::type_info& tid,
372 ::Bool_t silent ) const {
373
374 if( m_const ) {
375 if( ! silent ) {
376 ::Warning( "xAOD::THolder::getAs",
377 "Trying to retrieve const \"%s\" via non-const pointer \"%s\"",
378 m_type->GetName(),
379 SG::normalizedTypeinfoName( tid ).c_str() );
380 }
381 return nullptr;
382 }
383 return getImpl( tid, silent );
384 }
385
395 const void* THolder::getAsConst( const std::type_info& tid,
396 ::Bool_t silent ) const {
397
398 // In the generic case we just forward this call:
399 return getImpl( tid, silent );
400 }
401
402 const ::TClass* THolder::getClass() const {
403
404 return m_type;
405 }
406
407 ::TClass* THolder::getClass() {
408
409 return m_type;
410 }
411
412 const std::type_info* THolder::getTypeInfo() const {
413
414 return m_typeInfo;
415 }
416
422
423 // Delete the object using its dictionary:
424 if( m_object && m_owner &&
425 ( ! Internal::THolderCache::instance().decRef( m_object ) ) ) {
426 deleteObject();
427 }
428
429 // Create a new object:
430 m_owner = kTRUE;
431 m_object = m_type->New();
433
434 // Return gracefuly:
435 return;
436 }
437
439
440 // Check if we even have an object:
441 if( ! m_object ) {
442 return;
443 }
444
445 // Delete the object then:
446 if( m_type ) {
447 if( m_type->IsLoaded() ) {
448 m_type->Destructor( m_object );
449 }
450 // In certain situations it can happen that the memory cleanup for a
451 // particular TEvent object happens after ROOT already started to
452 // unload libraries from memory. In this case, since the application
453 // is anyway on its final leg, let's not bother the user with
454 // additional warnings about not being able to clean up after the
455 // managed object.
456 } else if( m_typeInfo ) {
457 const TVirtualDestructor* d =
459 if( d ) {
460 d->destruct( m_object );
461 } else {
462 ::Error( "xAOD::THolder::deleteObject",
463 XAOD_MESSAGE( "Couldn't delete managed object" ) );
464 }
465 } else {
466 ::Error( "xAOD::THolder::deleteObject",
467 XAOD_MESSAGE( "Couldn't delete managed object" ) );
468 }
469
470 return;
471 }
472
473} // namespace xAOD
Base class for elements of a container that can have aux data.
Manage index tracking and synchronization of auxiliary data.
#define XAOD_MESSAGE(MESSAGE)
Simple macro for printing error/verbose messages.
Define macros for attributes used to control the static checker.
#define ATLAS_THREAD_SAFE
Base class for elements of a container that can have aux data.
Definition AuxElement.h:483
Manage index tracking and synchronization of auxiliary data.
static THolderCache & instance()
Singleton accessor.
void addClass(const std::type_info &ti, ::TClass *cl)
Add the dictionary for a given type.
std::pair< bool, ::TClass * > getClass(const std::type_info &ti) const
Get the dictionary for a given type info.
int incRef(void *ptr)
Increment the reference count of an object in memory.
const TVirtualDestructor * get(const std::type_info &ti) const
Get the destructor for a given type.
static TDestructorRegistry & instance()
Function accessing the singleton instance of this type.
virtual ~THolder()
The destructor cleans out the memory used by the managed object.
Definition THolder.cxx:136
::Bool_t isOwner() const
Check whether the holder owns its object.
Definition THolder.cxx:253
void setConst()
Mark the object as const.
Definition THolder.cxx:285
TypeKind m_typeKind
Type of the object held.
Definition THolder.h:131
THolder & operator=(const THolder &rhs)
Assignment operator.
Definition THolder.cxx:151
THolder()
Default constructor.
Definition THolder.cxx:54
void setOwner(::Bool_t state=kTRUE)
Set whether the holder should own its object.
Definition THolder.cxx:258
::Bool_t isConst() const
Check if the object is const.
Definition THolder.cxx:280
const std::type_info * getTypeInfo() const
Definition THolder.cxx:412
void ** getPtr()
Return a typeless pointer to the held object's pointer.
Definition THolder.cxx:226
virtual void set(void *obj)
Replace the managed object.
Definition THolder.cxx:231
void * m_object
Typeless pointer to the object in memory.
Definition THolder.h:123
void deleteObject()
Internal function used to delete the managed object from memory.
Definition THolder.cxx:438
void renew()
Renew the object in memory.
Definition THolder.cxx:421
const ::TClass * getClass() const
Definition THolder.cxx:402
virtual void * getAs(const std::type_info &tid, ::Bool_t silent=kFALSE) const
Return the object as a specific pointer.
Definition THolder.cxx:371
::TClass * m_type
Concrete type of the object being held on to.
Definition THolder.h:125
::Bool_t m_const
Is the held object const?
Definition THolder.h:133
TypeKind
Type of the object held by this one.
Definition THolder.h:103
@ DATAVECTOR
A DataVector container.
Definition THolder.h:105
@ AUXELEMENT
A type inheriting from SG::AuxElement.
Definition THolder.h:106
@ OTHER
Some non-specified type.
Definition THolder.h:104
const std::type_info * m_typeInfo
Concrete type of the object, if it doesn't have a dictionary.
Definition THolder.h:127
void * getImpl(const std::type_info &tid, ::Bool_t silent=kFALSE) const
Internal function to get an object.
Definition THolder.cxx:297
virtual const void * getAsConst(const std::type_info &tid, ::Bool_t silent=kFALSE) const
Return the object as a specific, constant pointer.
Definition THolder.cxx:395
const void * get() const
Return a typeless const pointer to the held object.
Definition THolder.cxx:216
::Bool_t m_owner
A flag for whether the object owns what it points to.
Definition THolder.h:129
Base class for the templated destructor types.
Definition TDestructor.h:25
std::string normalizedTypeinfoName(const std::type_info &info)
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
Convert a type_info to a normalized string representation (matching the names used in the root dictio...