Empirical
mem_track.h
Go to the documentation of this file.
1 
26 #ifndef EMP_MEM_TRACK
27 #define EMP_MEM_TRACK
28 
29 
30 // If EMP_NDEBUG is turned on, turn off mem checks.
31 #ifdef EMP_NDEBUG
32 #define EMP_NO_MEM_CHECK
33 #endif
34 
35 
36 #include <map>
37 #include <string>
38 #include <sstream>
39 
40 #include "alert.h"
41 
42 #ifdef EMP_NO_MEM_CHECK
43 
44 #define EMP_TRACK_CONSTRUCT(CLASS_NAME)
45 #define EMP_TRACK_DESTRUCT(CLASS_NAME)
46 #define EMP_TRACK_COUNT(CLASS_NAME) 0
47 #define EMP_TRACK_STATUS std::string("(not in debug mode)")
48 
49 #else // DEBUG MODE!
50 
51 #define EMP_TRACK_CONSTRUCT(CLASS_NAME) emp::internal::TrackMem_Inc(#CLASS_NAME)
52 #define EMP_TRACK_DESTRUCT(CLASS_NAME) emp::internal::TrackMem_Dec(#CLASS_NAME)
53 #define EMP_TRACK_COUNT(CLASS_NAME) emp::internal::TrackMem_Count(#CLASS_NAME)
54 #define EMP_TRACK_STATUS emp::internal::TrackMem_Status()
55 
56 namespace emp {
57 
58  namespace internal {
59 
60  static std::map<std::string,int> & TrackMem_GetMap() {
61  static std::map<std::string,int> * track_mem_class_map = nullptr;
62  if (!track_mem_class_map) track_mem_class_map = new std::map<std::string,int>;
63  return *track_mem_class_map;
64  }
65 
66  static std::string TrackMem_Status() {
67  auto & mem_map = TrackMem_GetMap();
68 
69  std::stringstream ss;
70  for (auto stat : mem_map) {
71  ss << "[" << stat.first << "] : " << stat.second << std::endl;
72  }
73  return ss.str();
74  }
75 
76  static void TrackMem_Inc(const std::string & class_name) {
77  (void) class_name;
78  auto & mem_map = TrackMem_GetMap();
79  if (mem_map.find(class_name) == mem_map.end()) {
80  mem_map[class_name] = 0;
81  }
82  mem_map[class_name]++;
83  }
84 
85  static void TrackMem_Dec(const std::string & class_name) {
86  (void) class_name;
87  auto & mem_map = TrackMem_GetMap();
88 
89  // Make sure we are not trying to delete a class that was never registered!
90  if (mem_map.find(class_name) == mem_map.end()) {
91  emp::CappedAlert(3, "Trying to delete unknown: [", class_name,
92  "]; map size = ", mem_map.size());
93  abort();
94  }
95  mem_map[class_name]--;
96  if (mem_map[class_name] < 0) {
97  emp::CappedAlert(3, "Trying to delete too many: ", class_name);
98  abort();
99  }
100  }
101 
102  static int TrackMem_Count(const std::string & class_name) {
103  (void) class_name;
104  auto & mem_map = TrackMem_GetMap();
105 
106  if (mem_map.find(class_name) == mem_map.end()) {
107  return 0;
108  }
109  return mem_map[class_name];
110  }
111 
112  }
113 
114 }
115 #endif
116 
117 
118 #endif
static void CappedAlert(size_t cap, TYPE_SET...inputs)
A version of Alert that will cap how many times it can go off.
Definition: alert.h:38
static std::map< std::string, int > & TrackMem_GetMap()
Definition: mem_track.h:60
static void TrackMem_Dec(const std::string &class_name)
Definition: mem_track.h:85
static const PrintStr endl("<br>")
Pre-define emp::endl to insert a "<br>" and thus acting like a newline.
static void TrackMem_Inc(const std::string &class_name)
Definition: mem_track.h:76
static std::string TrackMem_Status()
Definition: mem_track.h:66
If we are in emscripten, make sure to include the header.
Definition: array.h:37
static int TrackMem_Count(const std::string &class_name)
Definition: mem_track.h:102