SST/macro
debug.h
Go to the documentation of this file.
1 /*
2  * This file is part of SST/macroscale:
3  * The macroscale architecture simulator from the SST suite.
4  * Copyright (c) 2009 Sandia Corporation.
5  * This software is distributed under the BSD License.
6  * Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
7  * the U.S. Government retains certain rights in this software.
8  * For more information, see the LICENSE file in the top
9  * SST/macroscale directory.
10  */
11 
12 #ifndef SPROCKIT_COMMON_DEBUG_H_INCLUDED
13 #define SPROCKIT_COMMON_DEBUG_H_INCLUDED
14 
15 #include <map>
16 #include <cstdio>
17 #include <string>
18 #include <stdint.h>
19 #include <iostream>
20 
21 #define MAX_DEBUG_SLOT 63 //64 bit integer
22 
23 namespace sprockit {
24 
25 /**
26  * @brief The debug_int class is an opaque wrapper around an integer
27  * used for checking if debug slots are active. The debug system
28  * will internally store a debug_int bitmask with 1's corresponding to all
29  * the debug slots activated via command line/param file.
30  * Every debug print request provides a debug_int to check against the
31  * internal bitmask. If the bitwise AND is zero, no active debug slots match
32  * and nothing is printed.
33  */
34 class debug_int
35 {
36  public:
37  debug_int(int slot){
38  init(slot);
39  }
40 
42  fields = 0;
43  }
44 
45  debug_int&
47  fields = ~fields;
48  return *this;
49  }
50 
51  void
52  init(int slot){
53  fields = (1ull) << slot;
54  }
55 
57  fields = rhs.fields;
58  return *this;
59  }
60 
61  operator bool() const {
62  return fields;
63  }
64 
65  std::string
66  to_string() const;
67 
68  uint64_t fields;
69 };
70 
71 inline debug_int
72 operator|(const debug_int& lhs, const debug_int& rhs)
73 {
74  debug_int ret;
75  ret.fields = lhs.fields | rhs.fields;
76  return ret;
77 }
78 
79 inline debug_int
80 operator&(const debug_int& lhs, const debug_int& rhs)
81 {
82  debug_int ret;
83  ret.fields = lhs.fields & rhs.fields;
84  return ret;
85 }
86 
87 /**
88  * @brief The debug_prefix_fxn class
89  * Produces a string prefix (dynamically, called every time)
90  * that can be registered with the debug system to add
91  * extra metadata to each debug print. An example usage
92  * would be to print timestamps in front of each debug string.
93  */
95 
96 public:
97  virtual std::string str() = 0;
98  virtual ~debug_prefix_fxn() = 0;
99 
100 };
101 
102 
103 class debug
104 {
105  public:
106  static std::map<std::string, debug_int*>* debug_ints_;
107  static std::map<std::string, std::string>* docstrings_;
109 
110  static void
111  delete_statics();
112 
113  /** The bitmask corresponding to all slots that were active at the beginning */
115  /** <= start_bitmask_ - some debug slots may have been selectively deactivated */
117  /** The number of debug slots that have been assigned unique indices */
118  static int num_bits_assigned;
119 
120  /**
121  * @brief turn_off Turn off all debug printing for all flags
122  */
123  static void
124  turn_off();
125 
126  /**
127  * @brief turn_on All debug flags that have been registered or
128  * previously turned on are reactivated
129  */
130  static void
131  turn_on();
132 
133  /**
134  * @brief turn_off Turn off a specific type of debug output
135  * @param di The identifier for the debug printing to deactivate
136  */
137  static void
138  turn_off(debug_int& di);
139 
140  /**
141  * @brief turn_on Turn on a specific type of debug output
142  * @param di The identifier for the debug printing to activate
143  */
144  static void
145  turn_on(debug_int& di);
146 
147  /**
148  * @brief register_debug_slot Register a new debug slot that can be
149  * activated via the command line or input file flags
150  * @param str The unique string identifying the slot
151  * @param dint_ptr A pointer to the debug integer that will be used for
152  * checking if debug printing is active. After registration,
153  * the debug integer pointed to will be updated.
154  * @param docstring An docstring describing the output produced by the debug
155  * when the debug slot is active
156  */
157  static void
158  register_debug_slot(const std::string& str,
159  debug_int* dint_ptr,
160  const std::string& docstring);
161 
162  /**
163  * @brief turn_on Another option for activating debug slots.
164  * Instead of activating via debug_int, activate via
165  * the associated string name
166  * @param str The string name associated with a debug slot
167  */
168  static void
169  turn_on(const std::string& str);
170 
171 
172  /**
173  * @brief print_debug_string Extra detail (prefix_fxn) can be added to
174  * each debug print. This provides a wrapper function that prints
175  * a given string with all associated prefix metadata. This ALWAYS prints,
176  * and is not dependent on certain debug slots being active.
177  * @param str The string to print after prefix metadata
178  * @param os The stream to print to
179  */
180  static void
181  print_debug_string(const std::string& str, std::ostream& os = std::cout);
182 
183  /**
184  * @brief slot_active Determine whether a debug slot is active. This is usually
185  * just a bitwise AND of the input parameter and a debug int
186  * with bits set to 1 for all the active slots
187  * @param allowed A debug integer indicating one or more possible
188  * debug slots
189  * @return Whether the slots in the input parameter match
190  * any of the active debug slots
191  */
192  static bool
193  slot_active(const debug_int& allowed);
194 
195  /**
196  * @brief print_all_debug_slots Print all of the possible debug slots
197  * registered with the debug system and any associated doc strings
198  * @param os The stream to print to
199  */
200  static void
201  print_all_debug_slots(std::ostream& os = std::cout);
202 
203  private:
204  /**
205  * @brief assign_slot If a given debug slot is activated, it must be assigned
206  * a unique integer index to allow bitwise AND checking of slots to see if they
207  * are active. This method should never be called by external code
208  * @param dint A reference to the integer that must be assigned a value
209  */
210  static void
211  assign_slot(debug_int& dint);
212 
213 };
214 
215 
216 /**
217  * @brief The debug_register_slot class
218  */
220  public:
221  /**
222  * @param str The unique string identifying the slot
223  * @param dint_ptr A pointer to the debug integer that will be used for
224  * checking if debug printing is active. After registration,
225  * the debug integer pointed to will be updated.
226  * @param docstring An docstring describing the output produced by the debug
227  * when the debug slot is active
228  */
229  debug_register_slot(const std::string& str,
230  debug_int* dint_ptr,
231  const std::string& docstring){
232  debug::register_debug_slot(str, dint_ptr, docstring);
233  }
234 };
235 
236 } // end of namespace sprockit
237 
238 /**
239  * Macro used for declaring a debug slot in a header file.
240  * This only declares the symbols used for debug printing
241  * without defining any of them. An arbitrary number
242  * of declarations are allowed.
243  */
244 #define DeclareDebugSlot(name) \
245  namespace sprockit { namespace dbg { \
246  extern debug_int name; \
247  } }
248 
249 
250 /**
251  * Macro used for defining all the symbols associated with a previously
252  * declared debug slot (DeclareDebugSlot). This should be defined once
253  * in a single source file. The declaration should always go in the
254  * global namespace. VA_ARGS here is an optional docstring
255  */
256 #define RegisterDebugSlot(name, ...) \
257  namespace sprockit { \
258  namespace dbg { \
259  debug_int name; \
260  debug_register_slot name##_debug_registerer(#name, &name, "" __VA_ARGS__); \
261  } }
262 
263 /**
264  * Declare and define a debug slot in a single macro in a source file.
265  * Should always go in global namespace
266  */
267 #define MakeDebugSlot(name, ...) \
268  DeclareDebugSlot(name) \
269  RegisterDebugSlot(name)
270 
271 #ifdef SPROCKIT_DISABLE_DEBUG
272 #define debug_printf(...) //eliminate completely
273 #else
274 //VA_ARGS[0] = format_str
275 #define debug_printf(slot_bitmask, ...) \
276  if (::sprockit::debug::slot_active(slot_bitmask)){ \
277  ::sprockit::debug::print_debug_string(::sprockit::printf(__VA_ARGS__)); \
278  }
279 #endif
280 
281 
282 
283 #endif
284 
The debug_register_slot class.
Definition: debug.h:219
debug_int operator&(const debug_int &lhs, const debug_int &rhs)
Definition: debug.h:80
static std::map< std::string, std::string > * docstrings_
Definition: debug.h:107
static void register_debug_slot(const std::string &str, debug_int *dint_ptr, const std::string &docstring)
register_debug_slot Register a new debug slot that can be activated via the command line or input fil...
void init(int slot)
Definition: debug.h:52
uint64_t fields
Definition: debug.h:68
std::string to_string() const
debug_int & operator=(const debug_int &rhs)
Definition: debug.h:56
debug_int operator|(const debug_int &lhs, const debug_int &rhs)
Definition: debug.h:72
static int num_bits_assigned
The number of debug slots that have been assigned unique indices.
Definition: debug.h:118
debug_int(int slot)
Definition: debug.h:37
debug_register_slot(const std::string &str, debug_int *dint_ptr, const std::string &docstring)
Definition: debug.h:229
static std::map< std::string, debug_int * > * debug_ints_
Definition: debug.h:106
The debug_prefix_fxn class Produces a string prefix (dynamically, called every time) that can be regi...
Definition: debug.h:94
static debug_int current_bitmask_
<= start_bitmask_ - some debug slots may have been selectively deactivated
Definition: debug.h:116
The debug_int class is an opaque wrapper around an integer used for checking if debug slots are activ...
Definition: debug.h:34
static debug_int start_bitmask_
The bitmask corresponding to all slots that were active at the beginning.
Definition: debug.h:114
static debug_prefix_fxn * prefix_fxn
Definition: debug.h:108
debug_int & operator~()
Definition: debug.h:46