ATLAS Offline Software
THolder.cxx
Go to the documentation of this file.
1 // Copyright (C) 2002-2023 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 
19 namespace {
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  }
41  return xAOD::THolder::OTHER;
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 
52 namespace 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 ) {
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 
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 
136 
137  // Delete the object using its dictionary:
138  if( m_object && m_owner &&
139  ( ! Internal::THolderCache::instance().decRef( m_object ) ) ) {
140  deleteObject();
141  }
142  }
143 
151 
152  // Check if we need to do anything:
153  if( &rhs == this ) return *this;
154 
155  // Clean up the previously managed object:
156  if( m_object && m_owner &&
157  ( ! Internal::THolderCache::instance().decRef( m_object ) ) ) {
158  deleteObject();
159  }
160 
161  // Do the copy:
162  m_object = rhs.m_object;
163  m_type = rhs.m_type;
164  m_typeInfo = rhs.m_typeInfo;
165  m_owner = rhs.m_owner;
166  m_typeKind = rhs.m_typeKind;
167  m_const = rhs.m_const;
168 
169  // Increase the object count:
170  if( m_object && m_owner ) {
172  }
173 
174  // Return this same object:
175  return *this;
176  }
177 
188 
189  // Check if we need to do anything:
190  if( &rhs == this ) return *this;
191 
192  // Clean up the previously managed object:
193  if( m_object && m_owner &&
194  ( ! Internal::THolderCache::instance().decRef( m_object ) ) ) {
195  deleteObject();
196  }
197 
198  // Do the copy:
199  m_object = rhs.m_object;
200  m_type = rhs.m_type;
201  m_typeInfo = rhs.m_typeInfo;
202  m_owner = rhs.m_owner;
203  m_typeKind = rhs.m_typeKind;
204  m_const = rhs.m_const;
205 
206  // Instead of doing anything with the shared count here, just make the
207  // parent not own the object anymore. The logic is the same as discussed
208  // in the move constructor.
209  rhs.m_owner = kFALSE;
210 
211  // Return this same object:
212  return *this;
213  }
214 
215  const void* THolder::get() const {
216 
217  return m_object;
218  }
219 
220  void* THolder::get() {
221 
222  return m_object;
223  }
224 
225  void** THolder::getPtr() {
226 
227  return &m_object;
228  }
229 
230  void THolder::set( void* obj ) {
231 
232  // Check if we need to do anything:
233  if( m_object == obj ) return;
234 
235  // Delete the previous object:
236  if( m_object && m_owner &&
237  ( ! Internal::THolderCache::instance().decRef( m_object ) ) ) {
238  deleteObject();
239  }
240 
241  // Hold on to the new object from now on:
242  m_object = obj;
243 
244  // Increase the object count:
245  if( m_object && m_owner ) {
247  }
248 
249  return;
250  }
251 
252  ::Bool_t THolder::isOwner() const {
253 
254  return m_owner;
255  }
256 
257  void THolder::setOwner( ::Bool_t state ) {
258 
259  // Check if anything needs to be done:
260  if( state == m_owner ) return;
261 
262  if( m_object && m_owner &&
263  ( ! Internal::THolderCache::instance().decRef( m_object ) ) ) {
264  ::Warning( "xAOD::THolder::setOwner",
265  "Deleting object %p no longer held by any owner",
266  m_object );
267  deleteObject();
268  }
269 
270  m_owner = state;
271 
272  if( m_object && m_owner ) {
274  }
275 
276  return;
277  }
278 
279  ::Bool_t THolder::isConst() const {
280 
281  return m_const;
282  }
283 
285 
286  m_const = kTRUE;
287  }
288 
296  void* THolder::getImpl( const std::type_info& tid,
297  ::Bool_t silent ) const {
298 
299  // If there is no dictionary for the object, then the logic is pretty
300  // simple:
301  if( ! m_type ) {
302  // Check if the user asked for the right type. Remember that in this
303  // case we can't return an object as its base type.
304  if( tid != *m_typeInfo ) {
305  if( ! silent ) {
306  const std::string heldType =
308  const std::string reqType =
310  ::Warning( "xAOD::THolder::getAs",
311  "Trying to retrieve %s object with a %s pointer",
312  heldType.c_str(), reqType.c_str() );
313  }
314  return 0;
315  }
316  // The user did ask for the correct type:
317  return m_object;
318  }
319 
320  // Check if we already know about this type:
321  auto userClass = Internal::THolderCache::instance().getClass( tid );
322  // If not, look for it now:
323  if( ! userClass.first ) {
324  userClass.second = ::TClass::GetClass( tid );
325  Internal::THolderCache::instance().addClass( tid, userClass.second );
326  }
327 
328  // If we still don't have a dictionary, that's an issue:
329  if( ! userClass.second ) {
330  if( ! silent ) {
331  ::Error( "xAOD::THolder::getAs",
332  XAOD_MESSAGE( "Couldn't access the dictionary for user "
333  "type: %s" ),
334  SG::normalizedTypeinfoName( tid ).c_str() );
335  }
336  return 0;
337  }
338 
339  // Check if the user requested a valid base class for the held type.
340  //
341  // Calling GetBaseClassOffset is in general not thread-safe as it could
342  // trigger the loading and parsing of StreamerInfo. However, we assume
343  // that this has already been done once we get here.
344  TClass* cl ATLAS_THREAD_SAFE = m_type;
345  const Int_t offset = cl->GetBaseClassOffset( userClass.second );
346  if( offset < 0 ) {
347  if( ! silent ) {
348  ::Warning( "xAOD::THolder::getAs",
349  "User class \"%s\" is not a valid base "
350  "of \"%s\"",
351  SG::normalizedTypeinfoName( tid ).c_str(),
352  m_type->GetName() );
353  }
354  return 0;
355  }
356 
357  // If all is fine, do the cast:
358  return ( static_cast< char* >( m_object ) + offset );
359  }
360 
370  void* THolder::getAs( const std::type_info& tid,
371  ::Bool_t silent ) const {
372 
373  if( m_const ) {
374  if( ! silent ) {
375  ::Warning( "xAOD::THolder::getAs",
376  "Trying to retrieve const \"%s\" via non-const pointer \"%s\"",
377  m_type->GetName(),
378  SG::normalizedTypeinfoName( tid ).c_str() );
379  }
380  return nullptr;
381  }
382  return getImpl( tid, silent );
383  }
384 
394  const void* THolder::getAsConst( const std::type_info& tid,
395  ::Bool_t silent ) const {
396 
397  // In the generic case we just forward this call:
398  return getImpl( tid, silent );
399  }
400 
401  const ::TClass* THolder::getClass() const {
402 
403  return m_type;
404  }
405 
406  ::TClass* THolder::getClass() {
407 
408  return m_type;
409  }
410 
411  const std::type_info* THolder::getTypeInfo() const {
412 
413  return m_typeInfo;
414  }
415 
420  void THolder::renew() {
421 
422  // Delete the object using its dictionary:
423  if( m_object && m_owner &&
424  ( ! Internal::THolderCache::instance().decRef( m_object ) ) ) {
425  deleteObject();
426  }
427 
428  // Create a new object:
429  m_owner = kTRUE;
430  m_object = m_type->New();
432 
433  // Return gracefuly:
434  return;
435  }
436 
438 
439  // Check if we even have an object:
440  if( ! m_object ) {
441  return;
442  }
443 
444  // Delete the object then:
445  if( m_type ) {
446  if( m_type->IsLoaded() ) {
447  m_type->Destructor( m_object );
448  }
449  // In certain situations it can happen that the memory cleanup for a
450  // particular TEvent object happens after ROOT already started to
451  // unload libraries from memory. In this case, since the application
452  // is anyway on its final leg, let's not bother the user with
453  // additional warnings about not being able to clean up after the
454  // managed object.
455  } else if( m_typeInfo ) {
456  const TVirtualDestructor* d =
458  if( d ) {
459  d->destruct( m_object );
460  } else {
461  ::Error( "xAOD::THolder::deleteObject",
462  XAOD_MESSAGE( "Couldn't delete managed object" ) );
463  }
464  } else {
465  ::Error( "xAOD::THolder::deleteObject",
466  XAOD_MESSAGE( "Couldn't delete managed object" ) );
467  }
468 
469  return;
470  }
471 
472 } // namespace xAOD
xAOD::THolder::OTHER
@ OTHER
Some non-specified type.
Definition: THolder.h:104
xAOD::THolder::isConst
::Bool_t isConst() const
Check if the object is const.
Definition: THolder.cxx:279
xAOD::THolder::operator=
THolder & operator=(const THolder &rhs)
Assignment operator.
Definition: THolder.cxx:150
xAOD::THolder::AUXELEMENT
@ AUXELEMENT
A type inheriting from SG::AuxElement.
Definition: THolder.h:106
xAOD::THolder::m_owner
::Bool_t m_owner
A flag for whether the object owns what it points to.
Definition: THolder.h:129
xAOD::THolder::setConst
void setConst()
Mark the object as const.
Definition: THolder.cxx:284
xAOD::THolder::setOwner
void setOwner(::Bool_t state=kTRUE)
Set whether the holder should own its object.
Definition: THolder.cxx:257
SG::normalizedTypeinfoName
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...
Definition: normalizedTypeinfoName.cxx:120
SG::AuxElement
Base class for elements of a container that can have aux data.
Definition: AuxElement.h:483
hist_file_dump.d
d
Definition: hist_file_dump.py:137
xAOD::THolder::DATAVECTOR
@ DATAVECTOR
A DataVector container.
Definition: THolder.h:105
xAOD::THolder::getAs
virtual void * getAs(const std::type_info &tid, ::Bool_t silent=kFALSE) const
Return the object as a specific pointer.
Definition: THolder.cxx:370
xAOD::THolder
This class takes care of holding EDM objects in memory.
Definition: THolder.h:35
xAOD::THolder::TypeKind
TypeKind
Type of the object held by this one.
Definition: THolder.h:103
xAOD::THolder::getPtr
void ** getPtr()
Return a typeless pointer to the held object's pointer.
Definition: THolder.cxx:225
xAOD::THolder::get
const void * get() const
Return a typeless const pointer to the held object.
Definition: THolder.cxx:215
xAOD::THolder::isOwner
::Bool_t isOwner() const
Check whether the holder owns its object.
Definition: THolder.cxx:252
xAOD::THolder::getImpl
void * getImpl(const std::type_info &tid, ::Bool_t silent=kFALSE) const
Internal function to get an object.
Definition: THolder.cxx:296
xAOD
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
Definition: ICaloAffectedTool.h:24
xAOD::THolder::deleteObject
void deleteObject()
Internal function used to delete the managed object from memory.
Definition: THolder.cxx:437
XAOD_MESSAGE
#define XAOD_MESSAGE(MESSAGE)
Simple macro for printing error/verbose messages.
Definition: Control/xAODRootAccess/xAODRootAccess/tools/Message.h:19
xAOD::Internal::THolderCache::addClass
void addClass(const std::type_info &ti, ::TClass *cl)
Add the dictionary for a given type.
Definition: THolderCache.cxx:49
AuxVectorBase.h
Manage index tracking and synchronization of auxiliary data.
SG::AuxVectorBase
Manage index tracking and synchronization of auxiliary data.
Definition: AuxVectorBase.h:98
TDestructorRegistry.h
xAOD::THolder::getClass
const ::TClass * getClass() const
Definition: THolder.cxx:401
m_type
TokenType m_type
the type
Definition: TProperty.cxx:44
xAOD::Internal::THolderCache::getClass
std::pair< bool, ::TClass * > getClass(const std::type_info &ti) const
Get the dictionary for a given type info.
Definition: THolderCache.cxx:35
xAOD::TVirtualDestructor
Base class for the templated destructor types.
Definition: TDestructor.h:25
xAOD::THolder::m_typeKind
TypeKind m_typeKind
Type of the object held.
Definition: THolder.h:131
Message.h
xAOD::THolder::m_const
::Bool_t m_const
Is the held object const?
Definition: THolder.h:133
xAOD::THolder::set
virtual void set(void *obj)
Replace the managed object.
Definition: THolder.cxx:230
test_pyathena.parent
parent
Definition: test_pyathena.py:15
xAOD::THolder::m_object
void * m_object
Typeless pointer to the object in memory.
Definition: THolder.h:123
xAOD::TDestructorRegistry::instance
static TDestructorRegistry & instance()
Function accessing the singleton instance of this type.
Definition: TDestructorRegistry.cxx:16
xAOD::THolder::m_type
::TClass * m_type
Concrete type of the object being held on to.
Definition: THolder.h:125
normalizedTypeinfoName.h
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
xAOD::Internal::THolderCache::instance
static THolderCache & instance()
Singleton accessor.
Definition: THolderCache.cxx:29
xAOD::Internal::THolderCache::incRef
int incRef(void *ptr)
Increment the reference count of an object in memory.
Definition: THolderCache.cxx:72
xAOD::THolder::THolder
THolder()
Default constructor.
Definition: THolder.cxx:54
xAOD::THolder::renew
void renew()
Renew the object in memory.
Definition: THolder.cxx:420
python.trfDecorators.silent
def silent(func)
Redirect stdout/err to /dev/null Useful wrapper to get rid of ROOT verbosity...
Definition: trfDecorators.py:24
xAOD::THolder::getTypeInfo
const std::type_info * getTypeInfo() const
Definition: THolder.cxx:411
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
THolder.h
convertTimingResiduals.offset
offset
Definition: convertTimingResiduals.py:71
xAOD::THolder::getAsConst
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:394
pickleTool.object
object
Definition: pickleTool.py:30
ATLAS_THREAD_SAFE
#define ATLAS_THREAD_SAFE
Definition: checker_macros.h:211
xAOD::THolder::m_typeInfo
const std::type_info * m_typeInfo
Concrete type of the object, if it doesn't have a dictionary.
Definition: THolder.h:127
xAOD::THolder::~THolder
virtual ~THolder()
The destructor cleans out the memory used by the managed object.
Definition: THolder.cxx:135
checker_macros.h
Define macros for attributes used to control the static checker.
python.PyAthena.obj
obj
Definition: PyAthena.py:132
THolderCache.h
dq_make_web_display.cl
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition: dq_make_web_display.py:26
xAOD::TDestructorRegistry::get
const TVirtualDestructor * get(const std::type_info &ti) const
Get the destructor for a given type.
Definition: TDestructorRegistry.cxx:23
plotBeamSpotMon.nc
int nc
Definition: plotBeamSpotMon.py:83
AuxElement.h
Base class for elements of a container that can have aux data.