DD4hep  1.30.0
Detector Description Toolkit for High Energy Physics
InstanceCount.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see $DD4hepINSTALL/LICENSE.
8 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
9 //
10 // Author : M.Frank
11 //
12 //==========================================================================
13 
15 #include <DD4hep/InstanceCount.h>
16 #include <DD4hep/Handle.h>
17 #include <DD4hep/Memory.h>
18 
20 #include <iostream>
21 #include <iomanip>
22 #include <cstdio>
23 #include <cstdlib>
24 #include <cstring>
25 #include <mutex>
26 #include <map>
27 
28 using namespace dd4hep;
29 
31 namespace {
32  typedef InstanceCount::Counter COUNT;
33  typedef std::map<const std::type_info*, COUNT*> TypeCounter;
34  typedef std::map<const std::string*, COUNT*> StringCounter;
35  static bool s_trace_instances = ::getenv("DD4HEP_TRACE") != 0;
36  static dd4hep_ptr<TypeCounter> s_typCounts(new TypeCounter());
37  static dd4hep_ptr<StringCounter> s_strCounts(new StringCounter());
38  static InstanceCount::Counter s_nullCount;
39  static InstanceCount::Counter s_thisCount;
40  static InstanceCount s_counter;
41  inline TypeCounter& types() {
42  return *(s_typCounts.get());
43  }
44  inline StringCounter& strings() {
45  return *(s_strCounts.get());
46  }
47  int s_global = 1;
48  struct _Global {
49  std::mutex lock;
50  _Global() {}
51  ~_Global() { s_global = 0; }
52  } s_globalObj;
53  int on_exit_destructors() {
54  static bool first = true;
55  if ( first && s_global == 0 && s_trace_instances ) {
56  first = false;
57  ::printf("Static out of order destructors occurred. Reference count table is unreliable.....\n");
58  }
59  return 1;
60  }
61 }
62 
65  s_thisCount.increment();
66 }
67 
70  s_thisCount.decrement();
71  if (0 == s_thisCount.value()) {
72  StringCounter::iterator i;
73  TypeCounter::iterator j;
74  dump(s_trace_instances ? ALL : NONE);
75  for (i = s_strCounts->begin(); i != s_strCounts->end(); ++i)
76  delete (*i).second;
77  for (j = s_typCounts->begin(); j != s_typCounts->end(); ++j)
78  delete (*j).second;
79  s_strCounts->clear();
80  s_typCounts->clear();
81  }
82 }
83 
86  return s_trace_instances;
87 }
88 
90 void InstanceCount::doTracing(bool value) {
91  s_trace_instances = value;
92 }
93 
96  Counter* cnt = s_trace_instances ? types()[&typ] : &s_nullCount;
97  return (0 != cnt) ? cnt : types()[&typ] = new Counter();
98 }
99 
102  Counter* cnt = s_trace_instances ? strings()[&typ] : &s_nullCount;
103  return (0 != cnt) ? cnt : strings()[&typ] = new Counter();
104 }
105 
106 #define COUNTER_LOCK std::lock_guard<std::mutex> _counter_lock(s_globalObj.lock);
107 
109 void InstanceCount::increment(const std::string& typ) {
110  if ( s_global ) {
112  getCounter(typ)->increment();
113  }
114  else
115  on_exit_destructors();
116 }
117 
119 void InstanceCount::decrement(const std::string& typ) {
120  if ( s_global ) {
122  getCounter(typ)->decrement();
123  }
124  else
125  on_exit_destructors();
126 }
127 
129 void InstanceCount::increment(const std::type_info& typ) {
130  if ( s_global ) {
132  getCounter(typ)->increment();
133  }
134  else
135  on_exit_destructors();
136 }
137 
139 void InstanceCount::decrement(const std::type_info& typ) {
140  if ( s_global ) {
142  getCounter(typ)->decrement();
143  }
144  else
145  on_exit_destructors();
146 }
147 
149 void InstanceCount::dump(int typ) {
150  bool need_footer = false;
151  if ((typ & STRING) && s_strCounts.get()) {
152  if ( !s_strCounts->empty() ) {
153  std::cout << "+--------------------------------------------------------------------------+" << std::endl;
154  std::cout << "| I n s t a n c e c o u n t e r s b y N A M E |" << std::endl;
155  std::cout << "+----------+---------+---------+-------------------------------------------+" << std::endl;
156  std::cout << "| Total | Max | Leaking | Type identifier |" << std::endl;
157  std::cout << "+----------+---------+---------+-------------------------------------------+" << std::endl;
158  long tot_instances=0, max_instances=0, now_instances=0;
159  for ( const auto& i : *s_strCounts ) {
160  std::cout << "|" << std::setw(10) << i.second->total()
161  << "|" << std::setw(9) << i.second->maximum()
162  << "|" << std::setw(9) << i.second->value()
163  << "|" << i.first->substr(0,80) << std::endl;
164  tot_instances += i.second->total();
165  max_instances += i.second->maximum();
166  now_instances += i.second->value();
167  }
168  std::cout << "+----------+---------+---------+-------------------------------------------+" << std::endl;
169  std::cout << "|" << std::setw(10) << tot_instances
170  << "|" << std::setw(9) << max_instances
171  << "|" << std::setw(9) << now_instances
172  << "|" << "Grand total (Sum of all counters)" << std::endl;
173  need_footer = true;
174  }
175  }
176  if ((typ & TYPEINFO) && s_typCounts.get()) {
177  if ( !s_typCounts->empty() ) {
178  std::cout << "+--------------------------------------------------------------------------+" << std::endl;
179  std::cout << "| I n s t a n c e c o u n t e r s b y T Y P E I N F O |" << std::endl;
180  std::cout << "+----------+---------+---------+-------------------------------------------+" << std::endl;
181  std::cout << "| Total | Max | Leaking | Type identifier |" << std::endl;
182  std::cout << "+----------+---------+---------+-------------------------------------------+" << std::endl;
183  long tot_instances=0, max_instances=0, now_instances=0;
184  for ( const auto& i : *s_typCounts ) {
185  std::string nam = typeName(*(i.first));
186  if ( nam.length() > 80 ) nam = nam.substr(0,80)+" ...";
187  std::cout << "|" << std::setw(10) << i.second->total()
188  << "|" << std::setw(9) << i.second->maximum()
189  << "|" << std::setw(9) << i.second->value()
190  << "|" << nam << std::endl;
191  tot_instances += i.second->total();
192  max_instances += i.second->maximum();
193  now_instances += i.second->value();
194  }
195  std::cout << "+----------+---------+---------+-------------------------------------------+" << std::endl;
196  std::cout << "|" << std::setw(10) << tot_instances
197  << "|" << std::setw(9) << max_instances
198  << "|" << std::setw(9) << now_instances
199  << "|" << "Grand total (Sum of all counters)" << std::endl;
200  need_footer = true;
201  }
202  }
203  if (need_footer) {
204  std::cout << "+----------+-------+-------------------------------------------+" << std::endl;
205  }
206 }
dd4hep::InstanceCount
Helper to support object counting when debugging memory leaks.
Definition: InstanceCount.h:31
dd4hep::InstanceCount::NONE
@ NONE
Definition: InstanceCount.h:36
dd4hep::InstanceCount::Counter
Internal class to could object constructions and destructions.
Definition: InstanceCount.h:50
dd4hep::InstanceCount::dump
static void dump(int which=ALL)
Dump list of instance counters.
Definition: InstanceCount.cpp:149
dd4hep::InstanceCount::Counter::increment
void increment()
Increment counter.
Definition: InstanceCount.h:66
dd4hep::InstanceCount::InstanceCount
InstanceCount()
Standard Constructor - No need to call explicitly.
Definition: InstanceCount.cpp:64
Handle.h
dd4hep::InstanceCount::increment
static void increment(T *)
Increment count according to type information.
Definition: InstanceCount.h:98
dd4hep::InstanceCount::doTracing
static void doTracing(bool value)
Enable/Disable tracing.
Definition: InstanceCount.cpp:90
dd4hep::InstanceCount::STRING
@ STRING
Definition: InstanceCount.h:37
dd4hep::InstanceCount::decrement
static void decrement(T *)
Decrement count according to type information.
Definition: InstanceCount.h:102
dd4hep::InstanceCount::doTrace
static bool doTrace()
Check if tracing is enabled.
Definition: InstanceCount.cpp:85
dd4hep::InstanceCount::TYPEINFO
@ TYPEINFO
Definition: InstanceCount.h:38
Memory.h
COUNTER_LOCK
#define COUNTER_LOCK
Definition: InstanceCount.cpp:106
dd4hep::InstanceCount::Counter::value
counter_t value() const
Access counter value.
Definition: InstanceCount.h:76
dd4hep
Namespace for the AIDA detector description toolkit.
Definition: AlignmentsCalib.h:28
dd4hep::InstanceCount::Counter::decrement
void decrement()
Decrement counter.
Definition: InstanceCount.h:72
InstanceCount.h
dd4hep::InstanceCount::getCounter
static Counter * getCounter(const std::type_info &typ)
Access counter object for local caching on optimizations.
Definition: InstanceCount.cpp:95
dd4hep::InstanceCount::~InstanceCount
virtual ~InstanceCount()
Standard Destructor - No need to call explicitly.
Definition: InstanceCount.cpp:69
dd4hep::dd4hep_ptr
Out version of the std auto_ptr implementation base either on auto_ptr or unique_ptr.
Definition: Memory.h:46
dd4hep::InstanceCount::ALL
@ ALL
Definition: InstanceCount.h:39