Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
DebugOutput.hpp
Go to the documentation of this file.
1 #ifndef moab_DEBUG_OUTPUT_HPP
2 #define moab_DEBUG_OUTPUT_HPP
3 
4 #include <cstdarg>
5 #include <cstdio>
6 #include <vector>
7 #include <iosfwd>
8 #include <string>
9 
10 #include "moab/Compiler.hpp"
11 #include "moab/CpuTimer.hpp"
12 
13 namespace moab
14 {
15 
16 class Range;
17 class DebugOutputStream;
18 
19 /**\brief Utility class for printing debug output
20  *
21  * This class implements line-oriented output. That is, it buffers
22  * output data until a newline is encountered, at which point it
23  * sends the output to the output stream followed by an explicit
24  * flush, and optionally prefixed with the MPI rank.
25  *
26  * This class also implements a verbosity filter for all output.
27  * The class instance has a verbosity limit. Each request
28  * for output has an associated verbosity level. If the verbosity
29  * level for the output is is less greater than the limit then
30  * the output is discarded. By convetion a verbosity limit
31  * of zero should indicate no output. Therefore all requests
32  * for output should have an associated verbosity level greater
33  * than or equal to one.
34  *
35  * \Note Any output not terminated with an newline character or
36  * followed by later output containing a newline character
37  * will not be flushed until the destructor is invoked.
38  * \Note C++-style IO (i.e. std::ostream) is not supported because
39  * it is necessarily inefficient for debug-type output. All
40  * formatting (e.g. converting arguments to strings, etc.) must
41  * be done even when output is disabled.
42  */
44 {
45 
46  public:
47  /**
48  *\param str Output stream to which to flush output
49  *\param verbosity Verbosity limit.
50  */
51  DebugOutput( DebugOutputStream* str, unsigned verbosity = 0 );
52  /**
53  *\param str Output stream to which to flush output
54  *\param rank MPI rank with which to prefix output.
55  *\param verbosity Verbosity limit.
56  */
57  DebugOutput( DebugOutputStream* str, int rank, unsigned verbosity = 0 );
58  /**
59  *\param str Output stream to which to flush output
60  *\param enabled Enable output: if not true, all output operations to nothing.
61  */
62  DebugOutput( FILE* str, unsigned verbosity = 0 );
63  /**
64  *\param str Output stream to which to flush output
65  *\param rank MPI rank with which to prefix output.
66  *\param verbosity Verbosity limit.
67  */
68  DebugOutput( FILE* str, int rank, unsigned verbosity = 0 );
69  /**
70  *\param str Output stream to which to flush output
71  *\param verbosity Verbosity limit.
72  */
73  DebugOutput( std::ostream& str, unsigned verbosity = 0 );
74  /**
75  *\param str Output stream to which to flush output
76  *\param rank MPI rank with which to prefix output.
77  *\param verbosity Verbosity limit.
78  */
79  DebugOutput( std::ostream& str, int rank, unsigned verbosity = 0 );
80 
81  /**
82  *\param pfx Prefix for output
83  *\param str Output stream to which to flush output
84  *\param verbosity Verbosity limit.
85  */
86  DebugOutput( const char* pfx, DebugOutputStream* str, unsigned verbosity = 0 );
87  /**
88  *\param pfx Prefix for output
89  *\param str Output stream to which to flush output
90  *\param rank MPI rank with which to prefix output.
91  *\param verbosity Verbosity limit.
92  */
93  DebugOutput( const char* pfx, DebugOutputStream* str, int rank, unsigned verbosity = 0 );
94  /**
95  *\param pfx Prefix for output
96  *\param str Output stream to which to flush output
97  *\param enabled Enable output: if not true, all output operations to nothing.
98  */
99  DebugOutput( const char* pfx, FILE* str, unsigned verbosity = 0 );
100  /**
101  *\param pfx Prefix for output
102  *\param str Output stream to which to flush output
103  *\param rank MPI rank with which to prefix output.
104  *\param verbosity Verbosity limit.
105  */
106  DebugOutput( const char* pfx, FILE* str, int rank, unsigned verbosity = 0 );
107  /**
108  *\param pfx Prefix for output
109  *\param str Output stream to which to flush output
110  *\param verbosity Verbosity limit.
111  */
112  DebugOutput( const char* pfx, std::ostream& str, unsigned verbosity = 0 );
113  /**
114  *\param pfx Prefix for output
115  *\param str Output stream to which to flush output
116  *\param rank MPI rank with which to prefix output.
117  *\param verbosity Verbosity limit.
118  */
119  DebugOutput( const char* pfx, std::ostream& str, int rank, unsigned verbosity = 0 );
120 
121  DebugOutput( const DebugOutput& copy );
122  DebugOutput& operator=( const DebugOutput& copy );
123 
124  /**
125  * Destructor flushes any remaining output that wasn't followed
126  * by a newline character.
127  */
128  ~DebugOutput();
129 
130  //!\brief Check if MPI rank has been set.
131  bool have_rank() const
132  {
133  return mpiRank >= 0;
134  }
135  //!\brief Get MPI rank.
136  int get_rank() const
137  {
138  return mpiRank;
139  }
140  //!\brief Set MPI rank.
141  void set_rank( int rank )
142  {
143  mpiRank = rank;
144  }
145  //!\brief Set MPI rank to the rank of this proccess in MPI_COMM_WORLD,
146  //! or zero if MOAB is build w/out MPI.
147  void use_world_rank();
148 
149  //!\brief Only print debug output from N processes
151  {
152  if( mpiRank >= N ) verbosityLimit = 0;
153  }
154 
155  //!\brief Get verbosity limit
156  unsigned get_verbosity() const
157  {
158  return verbosityLimit;
159  }
160  //!\brief Set verbosity limit
161  void set_verbosity( unsigned val )
162  {
163  verbosityLimit = val;
164  }
165 
166  //!\brief Get line prefix
167  const std::string& get_prefix() const
168  {
169  return linePfx;
170  }
171  //!\brief Set line prefix
172  void set_prefix( const std::string& str )
173  {
174  linePfx = str;
175  }
176 
177  //!\brief Output the specified string iff output is enabled.
178  void print( int verbosity, const char* str )
179  {
180  if( check( verbosity ) ) print_real( str );
181  }
182 
183  //!\brief Output the specified string iff output is enabled.
184  void print( int verbosity, const std::string& str )
185  {
186  if( check( verbosity ) ) print_real( str );
187  }
188 
189  //!\brief Output the specified printf-formatted output iff output is enabled
190  inline void printf( int verbosity, const char* fmt, ... ) MB_PRINTF( 2 );
191 
192  //!\brief Output the specified string iff output is enabled.
193  //!
194  //! Include current CPU time (as returned by clock()) in output.
195  void tprint( int verbosity, const char* str )
196  {
197  if( check( verbosity ) ) tprint_real( str );
198  }
199 
200  //!\brief Output the specified string iff output is enabled.
201  //!
202  //! Include current CPU time (as returned by clock()) in output.
203  void tprint( int verbosity, const std::string& str )
204  {
205  if( check( verbosity ) ) tprint_real( str );
206  }
207 
208  //!\brief Output the specified printf-formatted output iff output is enabled
209  //!
210  //! Include current CPU time (as returned by clock()) in output.
211  inline void tprintf( int verbosity, const char* fmt, ... ) MB_PRINTF( 2 );
212 
213  //!\brief Print the contents of a moab::Range
214  //!\param pfx String to print after default class prefix and before range contents
215  void print( int verbosity, const char* pfx, const Range& range )
216  {
217  if( check( verbosity ) ) list_range_real( pfx, range );
218  }
219  //!\brief Print the contents of a moab::Range
220  void print( int verbosity, const Range& range )
221  {
222  if( check( verbosity ) ) list_range_real( 0, range );
223  }
224 
225  //!\brief Print the contents of a moab::Range as numerical values only
226  //!\param pfx String to print after default class prefix and before range contents
227  void print_ints( int verbosity, const char* pfx, const Range& range )
228  {
229  if( check( verbosity ) ) list_ints_real( pfx, range );
230  }
231  //!\brief Print the contents of a moab::Range as numerical values only
232  void print_ints( int verbosity, const Range& range )
233  {
234  if( check( verbosity ) ) list_ints_real( 0, range );
235  }
236 
237  private:
238  std::string linePfx;
240  int mpiRank;
241  unsigned verbosityLimit;
243 
244  void tprint();
245 
246  void list_range_real( const char* pfx, const Range& range );
247  void list_ints_real( const char* pfx, const Range& range );
248  void print_real( const char* buffer );
249  void print_real( const std::string& str );
250  void tprint_real( const char* buffer );
251  void tprint_real( const std::string& str );
252 
253  // Function must be passed to copies of the same va_list because
254  // a) it might have to call vs(n)printf twice, b) vs(n)printf modifies
255  // the va_list such that it cannot be reused, and c) va_copy is not
256  // (yet) portable (c99, no c++ standard).
257  void print_real( const char* buffer, va_list args1, va_list args2 );
258  void tprint_real( const char* buffer, va_list args1, va_list args2 );
259  void process_line_buffer();
260 
261  std::vector< char > lineBuffer;
262 
263  inline bool check( unsigned verbosity )
264  {
265  return verbosity <= verbosityLimit;
266  }
267 };
268 
270 {
271  protected:
272  friend class DebugOutput;
274 
275  public:
277  virtual ~DebugOutputStream();
278  virtual void println( const char* pfx, const char* str ) = 0;
279  virtual void println( int rank, const char* pfx, const char* str ) = 0;
280 };
281 
282 void DebugOutput::printf( int verbosity, const char* fmt, ... )
283 {
284  if( check( verbosity ) )
285  {
286  va_list args1, args2;
287  va_start( args1, fmt );
288  va_start( args2, fmt );
289  print_real( fmt, args1, args2 );
290  va_end( args2 );
291  va_end( args1 );
292  }
293 }
294 
295 void DebugOutput::tprintf( int verbosity, const char* fmt, ... )
296 {
297  if( check( verbosity ) )
298  {
299  va_list args1, args2;
300  va_start( args1, fmt );
301  va_start( args2, fmt );
302  tprint_real( fmt, args1, args2 );
303  va_end( args2 );
304  va_end( args1 );
305  }
306 }
307 
308 } // namespace moab
309 
310 #endif