File indexing completed on 2025-01-18 09:13:55
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <DD4hep/InstanceCount.h>
0016 #include <DD4hep/Handle.h>
0017 #include <DD4hep/Memory.h>
0018
0019
0020 #include <iostream>
0021 #include <iomanip>
0022 #include <cstdio>
0023 #include <cstdlib>
0024 #include <cstring>
0025 #include <mutex>
0026 #include <map>
0027
0028 using namespace dd4hep;
0029
0030
0031 namespace {
0032 typedef InstanceCount::Counter COUNT;
0033 typedef std::map<const std::type_info*, COUNT*> TypeCounter;
0034 typedef std::map<const std::string*, COUNT*> StringCounter;
0035 static bool s_trace_instances = ::getenv("DD4HEP_TRACE") != 0;
0036 static dd4hep_ptr<TypeCounter> s_typCounts(new TypeCounter());
0037 static dd4hep_ptr<StringCounter> s_strCounts(new StringCounter());
0038 static InstanceCount::Counter s_nullCount;
0039 static InstanceCount::Counter s_thisCount;
0040 static InstanceCount s_counter;
0041 inline TypeCounter& types() {
0042 return *(s_typCounts.get());
0043 }
0044 inline StringCounter& strings() {
0045 return *(s_strCounts.get());
0046 }
0047 int s_global = 1;
0048 struct _Global {
0049 std::mutex lock;
0050 _Global() {}
0051 ~_Global() { s_global = 0; }
0052 } s_globalObj;
0053 int on_exit_destructors() {
0054 static bool first = true;
0055 if ( first && s_global == 0 && s_trace_instances ) {
0056 first = false;
0057 ::printf("Static out of order destructors occurred. Reference count table is unreliable.....\n");
0058 }
0059 return 1;
0060 }
0061 }
0062
0063
0064 InstanceCount::InstanceCount() {
0065 s_thisCount.increment();
0066 }
0067
0068
0069 InstanceCount::~InstanceCount() {
0070 s_thisCount.decrement();
0071 if (0 == s_thisCount.value()) {
0072 StringCounter::iterator i;
0073 TypeCounter::iterator j;
0074 dump(s_trace_instances ? ALL : NONE);
0075 for (i = s_strCounts->begin(); i != s_strCounts->end(); ++i)
0076 delete (*i).second;
0077 for (j = s_typCounts->begin(); j != s_typCounts->end(); ++j)
0078 delete (*j).second;
0079 s_strCounts->clear();
0080 s_typCounts->clear();
0081 }
0082 }
0083
0084
0085 bool InstanceCount::doTrace() {
0086 return s_trace_instances;
0087 }
0088
0089
0090 void InstanceCount::doTracing(bool value) {
0091 s_trace_instances = value;
0092 }
0093
0094
0095 InstanceCount::Counter* InstanceCount::getCounter(const std::type_info& typ) {
0096 Counter* cnt = s_trace_instances ? types()[&typ] : &s_nullCount;
0097 return (0 != cnt) ? cnt : types()[&typ] = new Counter();
0098 }
0099
0100
0101 InstanceCount::Counter* InstanceCount::getCounter(const std::string& typ) {
0102 Counter* cnt = s_trace_instances ? strings()[&typ] : &s_nullCount;
0103 return (0 != cnt) ? cnt : strings()[&typ] = new Counter();
0104 }
0105
0106 #define COUNTER_LOCK std::lock_guard<std::mutex> _counter_lock(s_globalObj.lock);
0107
0108
0109 void InstanceCount::increment(const std::string& typ) {
0110 if ( s_global ) {
0111 COUNTER_LOCK
0112 getCounter(typ)->increment();
0113 }
0114 else
0115 on_exit_destructors();
0116 }
0117
0118
0119 void InstanceCount::decrement(const std::string& typ) {
0120 if ( s_global ) {
0121 COUNTER_LOCK
0122 getCounter(typ)->decrement();
0123 }
0124 else
0125 on_exit_destructors();
0126 }
0127
0128
0129 void InstanceCount::increment(const std::type_info& typ) {
0130 if ( s_global ) {
0131 COUNTER_LOCK
0132 getCounter(typ)->increment();
0133 }
0134 else
0135 on_exit_destructors();
0136 }
0137
0138
0139 void InstanceCount::decrement(const std::type_info& typ) {
0140 if ( s_global ) {
0141 COUNTER_LOCK
0142 getCounter(typ)->decrement();
0143 }
0144 else
0145 on_exit_destructors();
0146 }
0147
0148
0149 void InstanceCount::dump(int typ) {
0150 bool need_footer = false;
0151 if ((typ & STRING) && s_strCounts.get()) {
0152 if ( !s_strCounts->empty() ) {
0153 std::cout << "+--------------------------------------------------------------------------+" << std::endl;
0154 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;
0155 std::cout << "+----------+---------+---------+-------------------------------------------+" << std::endl;
0156 std::cout << "| Total | Max | Leaking | Type identifier |" << std::endl;
0157 std::cout << "+----------+---------+---------+-------------------------------------------+" << std::endl;
0158 long tot_instances=0, max_instances=0, now_instances=0;
0159 for ( const auto& i : *s_strCounts ) {
0160 std::cout << "|" << std::setw(10) << i.second->total()
0161 << "|" << std::setw(9) << i.second->maximum()
0162 << "|" << std::setw(9) << i.second->value()
0163 << "|" << i.first->substr(0,80) << std::endl;
0164 tot_instances += i.second->total();
0165 max_instances += i.second->maximum();
0166 now_instances += i.second->value();
0167 }
0168 std::cout << "+----------+---------+---------+-------------------------------------------+" << std::endl;
0169 std::cout << "|" << std::setw(10) << tot_instances
0170 << "|" << std::setw(9) << max_instances
0171 << "|" << std::setw(9) << now_instances
0172 << "|" << "Grand total (Sum of all counters)" << std::endl;
0173 need_footer = true;
0174 }
0175 }
0176 if ((typ & TYPEINFO) && s_typCounts.get()) {
0177 if ( !s_typCounts->empty() ) {
0178 std::cout << "+--------------------------------------------------------------------------+" << std::endl;
0179 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;
0180 std::cout << "+----------+---------+---------+-------------------------------------------+" << std::endl;
0181 std::cout << "| Total | Max | Leaking | Type identifier |" << std::endl;
0182 std::cout << "+----------+---------+---------+-------------------------------------------+" << std::endl;
0183 long tot_instances=0, max_instances=0, now_instances=0;
0184 for ( const auto& i : *s_typCounts ) {
0185 std::string nam = typeName(*(i.first));
0186 if ( nam.length() > 80 ) nam = nam.substr(0,80)+" ...";
0187 std::cout << "|" << std::setw(10) << i.second->total()
0188 << "|" << std::setw(9) << i.second->maximum()
0189 << "|" << std::setw(9) << i.second->value()
0190 << "|" << nam << std::endl;
0191 tot_instances += i.second->total();
0192 max_instances += i.second->maximum();
0193 now_instances += i.second->value();
0194 }
0195 std::cout << "+----------+---------+---------+-------------------------------------------+" << std::endl;
0196 std::cout << "|" << std::setw(10) << tot_instances
0197 << "|" << std::setw(9) << max_instances
0198 << "|" << std::setw(9) << now_instances
0199 << "|" << "Grand total (Sum of all counters)" << std::endl;
0200 need_footer = true;
0201 }
0202 }
0203 if (need_footer) {
0204 std::cout << "+----------+-------+-------------------------------------------+" << std::endl;
0205 }
0206 }