Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights reserved. 2 // See the file tools.license for terms. 3 4 #ifndef tools_mem 5 #define tools_mem 6 7 #ifdef TOOLS_MEM 8 // to count instances. 9 10 // WARNING : it uses writable static data, then it is NOT thread safe. 11 // This class must be used for debugging only. 12 13 #include <ostream> 14 #include <list> 15 #include <string> 16 #include <cstring> //strcmp 17 18 namespace tools { 19 20 class mem { 21 static const std::string& s_class() { 22 static const std::string s_v("tools::mem"); 23 return s_v; 24 } 25 protected: 26 mem(){increment(s_class().c_str());} 27 virtual ~mem(){decrement(s_class().c_str());} 28 mem(const mem&){} 29 mem& operator=(const mem&){return *this;} 30 public: 31 //static void increment(){counter()++;} 32 //static void decrement(){counter()--;} 33 34 static void increment(const char* a_class){ 35 counter()++; 36 if(check_by_class()) { 37 mem_list::iterator it; 38 for(it=list().begin();it!=list().end();++it) { 39 if(!::strcmp((*it).first.c_str(),a_class)) { 40 (*it).second++; 41 return; 42 } 43 } 44 list().push_back(std::pair<std::string,int>(std::string(a_class),1)); 45 } 46 } 47 48 static void decrement(const char* a_class,unsigned int a_num = 1){ 49 counter() -= a_num; 50 if(check_by_class()) { 51 mem_list::iterator it; 52 for(it=list().begin();it!=list().end();++it) { 53 if(!::strcmp((*it).first.c_str(),a_class)) { 54 (*it).second -= a_num; 55 return; 56 } 57 } 58 list().push_back(std::pair<std::string,int>(std::string(a_class),-int(a_num))); 59 } 60 } 61 62 static void set_check_by_class(bool a_value) { 63 check_by_class() = a_value; 64 } 65 /* 66 static void reset(); 67 */ 68 69 static void balance(std::ostream& a_out){ 70 if(counter()) { 71 a_out << "tools::mem::balance :" 72 << " bad global object balance : " << counter() 73 << std::endl; 74 if(check_by_class()) { 75 a_out << "tools::mem::balance :" 76 << " check by class was enabled." 77 << std::endl; 78 } else { 79 a_out << "tools::mem::balance :" 80 << " check by class was disabled." 81 << std::endl; 82 } 83 } 84 mem_list::iterator it; 85 for(it=list().begin();it!=list().end();++it) { 86 if((*it).second) { 87 a_out << "tools::mem::balance :" 88 << " for class " << (*it).first 89 << ", bad object balance : " << (*it).second 90 << std::endl; 91 } 92 } 93 list().clear(); 94 } 95 96 protected: 97 public: //for MT disconnection (see test/mt_root_ntuple.cpp). 98 static int& counter() { 99 static int s_count = 0; 100 return s_count; 101 } 102 103 static bool& check_by_class() { 104 static bool s_check_by_class = false; 105 return s_check_by_class; 106 } 107 protected: 108 109 typedef std::list< std::pair<std::string,int> > mem_list; 110 111 static mem_list& list() { 112 static mem_list* s_list = new mem_list(); //have it on the heap, so that an atexit logic works. 113 return *s_list; 114 } 115 }; 116 117 inline const std::string& s_new() { 118 static const std::string s_v("new"); 119 return s_v; 120 } 121 122 inline const std::string& s_malloc() { 123 static const std::string s_v("malloc"); 124 return s_v; 125 } 126 127 inline const std::string& s_tex() { 128 static const std::string s_v("tex"); 129 return s_v; 130 } 131 132 inline const std::string& s_gsto() { 133 static const std::string s_v("gsto"); 134 return s_v; 135 } 136 137 } 138 139 #endif 140 141 #endif 142 143 144 145