MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 #ifndef moab_DEBUG_OUTPUT_HPP 00002 #define moab_DEBUG_OUTPUT_HPP 00003 00004 #include <cstdarg> 00005 #include <cstdio> 00006 #include <vector> 00007 #include <iosfwd> 00008 #include <string> 00009 00010 #include "moab/Compiler.hpp" 00011 #include "moab/CpuTimer.hpp" 00012 00013 namespace moab 00014 { 00015 00016 class Range; 00017 class DebugOutputStream; 00018 00019 /**\brief Utility class for printing debug output 00020 * 00021 * This class implements line-oriented output. That is, it buffers 00022 * output data until a newline is encountered, at which point it 00023 * sends the output to the output stream followed by an explicit 00024 * flush, and optionally prefixed with the MPI rank. 00025 * 00026 * This class also implements a verbosity filter for all output. 00027 * The class instance has a verbosity limit. Each request 00028 * for output has an associated verbosity level. If the verbosity 00029 * level for the output is is less greater than the limit then 00030 * the output is discarded. By convetion a verbosity limit 00031 * of zero should indicate no output. Therefore all requests 00032 * for output should have an associated verbosity level greater 00033 * than or equal to one. 00034 * 00035 * \Note Any output not terminated with an newline character or 00036 * followed by later output containing a newline character 00037 * will not be flushed until the destructor is invoked. 00038 * \Note C++-style IO (i.e. std::ostream) is not supported because 00039 * it is necessarily inefficient for debug-type output. All 00040 * formatting (e.g. converting arguments to strings, etc.) must 00041 * be done even when output is disabled. 00042 */ 00043 class DebugOutput 00044 { 00045 00046 public: 00047 /** 00048 *\param str Output stream to which to flush output 00049 *\param verbosity Verbosity limit. 00050 */ 00051 DebugOutput( DebugOutputStream* str, unsigned verbosity = 0 ); 00052 /** 00053 *\param str Output stream to which to flush output 00054 *\param rank MPI rank with which to prefix output. 00055 *\param verbosity Verbosity limit. 00056 */ 00057 DebugOutput( DebugOutputStream* str, int rank, unsigned verbosity = 0 ); 00058 /** 00059 *\param str Output stream to which to flush output 00060 *\param enabled Enable output: if not true, all output operations to nothing. 00061 */ 00062 DebugOutput( FILE* str, unsigned verbosity = 0 ); 00063 /** 00064 *\param str Output stream to which to flush output 00065 *\param rank MPI rank with which to prefix output. 00066 *\param verbosity Verbosity limit. 00067 */ 00068 DebugOutput( FILE* str, int rank, unsigned verbosity = 0 ); 00069 /** 00070 *\param str Output stream to which to flush output 00071 *\param verbosity Verbosity limit. 00072 */ 00073 DebugOutput( std::ostream& str, unsigned verbosity = 0 ); 00074 /** 00075 *\param str Output stream to which to flush output 00076 *\param rank MPI rank with which to prefix output. 00077 *\param verbosity Verbosity limit. 00078 */ 00079 DebugOutput( std::ostream& str, int rank, unsigned verbosity = 0 ); 00080 00081 /** 00082 *\param pfx Prefix for output 00083 *\param str Output stream to which to flush output 00084 *\param verbosity Verbosity limit. 00085 */ 00086 DebugOutput( const char* pfx, DebugOutputStream* str, unsigned verbosity = 0 ); 00087 /** 00088 *\param pfx Prefix for output 00089 *\param str Output stream to which to flush output 00090 *\param rank MPI rank with which to prefix output. 00091 *\param verbosity Verbosity limit. 00092 */ 00093 DebugOutput( const char* pfx, DebugOutputStream* str, int rank, unsigned verbosity = 0 ); 00094 /** 00095 *\param pfx Prefix for output 00096 *\param str Output stream to which to flush output 00097 *\param enabled Enable output: if not true, all output operations to nothing. 00098 */ 00099 DebugOutput( const char* pfx, FILE* str, unsigned verbosity = 0 ); 00100 /** 00101 *\param pfx Prefix for output 00102 *\param str Output stream to which to flush output 00103 *\param rank MPI rank with which to prefix output. 00104 *\param verbosity Verbosity limit. 00105 */ 00106 DebugOutput( const char* pfx, FILE* str, int rank, unsigned verbosity = 0 ); 00107 /** 00108 *\param pfx Prefix for output 00109 *\param str Output stream to which to flush output 00110 *\param verbosity Verbosity limit. 00111 */ 00112 DebugOutput( const char* pfx, std::ostream& str, unsigned verbosity = 0 ); 00113 /** 00114 *\param pfx Prefix for output 00115 *\param str Output stream to which to flush output 00116 *\param rank MPI rank with which to prefix output. 00117 *\param verbosity Verbosity limit. 00118 */ 00119 DebugOutput( const char* pfx, std::ostream& str, int rank, unsigned verbosity = 0 ); 00120 00121 DebugOutput( const DebugOutput& copy ); 00122 DebugOutput& operator=( const DebugOutput& copy ); 00123 00124 /** 00125 * Destructor flushes any remaining output that wasn't followed 00126 * by a newline character. 00127 */ 00128 ~DebugOutput(); 00129 00130 //!\brief Check if MPI rank has been set. 00131 bool have_rank() const 00132 { 00133 return mpiRank >= 0; 00134 } 00135 //!\brief Get MPI rank. 00136 int get_rank() const 00137 { 00138 return mpiRank; 00139 } 00140 //!\brief Set MPI rank. 00141 void set_rank( int rank ) 00142 { 00143 mpiRank = rank; 00144 } 00145 //!\brief Set MPI rank to the rank of this proccess in MPI_COMM_WORLD, 00146 //! or zero if MOAB is build w/out MPI. 00147 void use_world_rank(); 00148 00149 //!\brief Only print debug output from N processes 00150 void limit_output_to_first_N_procs( int N ) 00151 { 00152 if( mpiRank >= N ) verbosityLimit = 0; 00153 } 00154 00155 //!\brief Get verbosity limit 00156 unsigned get_verbosity() const 00157 { 00158 return verbosityLimit; 00159 } 00160 //!\brief Set verbosity limit 00161 void set_verbosity( unsigned val ) 00162 { 00163 verbosityLimit = val; 00164 } 00165 00166 //!\brief Get line prefix 00167 const std::string& get_prefix() const 00168 { 00169 return linePfx; 00170 } 00171 //!\brief Set line prefix 00172 void set_prefix( const std::string& str ) 00173 { 00174 linePfx = str; 00175 } 00176 00177 //!\brief Output the specified string iff output is enabled. 00178 void print( int verbosity, const char* str ) 00179 { 00180 if( check( verbosity ) ) print_real( str ); 00181 } 00182 00183 //!\brief Output the specified string iff output is enabled. 00184 void print( int verbosity, const std::string& str ) 00185 { 00186 if( check( verbosity ) ) print_real( str ); 00187 } 00188 00189 //!\brief Output the specified printf-formatted output iff output is enabled 00190 inline void printf( int verbosity, const char* fmt, ... ) MB_PRINTF( 2 ); 00191 00192 //!\brief Output the specified string iff output is enabled. 00193 //! 00194 //! Include current CPU time (as returned by clock()) in output. 00195 void tprint( int verbosity, const char* str ) 00196 { 00197 if( check( verbosity ) ) tprint_real( str ); 00198 } 00199 00200 //!\brief Output the specified string iff output is enabled. 00201 //! 00202 //! Include current CPU time (as returned by clock()) in output. 00203 void tprint( int verbosity, const std::string& str ) 00204 { 00205 if( check( verbosity ) ) tprint_real( str ); 00206 } 00207 00208 //!\brief Output the specified printf-formatted output iff output is enabled 00209 //! 00210 //! Include current CPU time (as returned by clock()) in output. 00211 inline void tprintf( int verbosity, const char* fmt, ... ) MB_PRINTF( 2 ); 00212 00213 //!\brief Print the contents of a moab::Range 00214 //!\param pfx String to print after default class prefix and before range contents 00215 void print( int verbosity, const char* pfx, const Range& range ) 00216 { 00217 if( check( verbosity ) ) list_range_real( pfx, range ); 00218 } 00219 //!\brief Print the contents of a moab::Range 00220 void print( int verbosity, const Range& range ) 00221 { 00222 if( check( verbosity ) ) list_range_real( 0, range ); 00223 } 00224 00225 //!\brief Print the contents of a moab::Range as numerical values only 00226 //!\param pfx String to print after default class prefix and before range contents 00227 void print_ints( int verbosity, const char* pfx, const Range& range ) 00228 { 00229 if( check( verbosity ) ) list_ints_real( pfx, range ); 00230 } 00231 //!\brief Print the contents of a moab::Range as numerical values only 00232 void print_ints( int verbosity, const Range& range ) 00233 { 00234 if( check( verbosity ) ) list_ints_real( 0, range ); 00235 } 00236 00237 private: 00238 std::string linePfx; 00239 DebugOutputStream* outputImpl; 00240 int mpiRank; 00241 unsigned verbosityLimit; 00242 CpuTimer cpuTi; 00243 00244 void tprint(); 00245 00246 void list_range_real( const char* pfx, const Range& range ); 00247 void list_ints_real( const char* pfx, const Range& range ); 00248 void print_real( const char* buffer ); 00249 void print_real( const std::string& str ); 00250 void tprint_real( const char* buffer ); 00251 void tprint_real( const std::string& str ); 00252 00253 // Function must be passed to copies of the same va_list because 00254 // a) it might have to call vs(n)printf twice, b) vs(n)printf modifies 00255 // the va_list such that it cannot be reused, and c) va_copy is not 00256 // (yet) portable (c99, no c++ standard). 00257 void print_real( const char* buffer, va_list args1, va_list args2 ); 00258 void tprint_real( const char* buffer, va_list args1, va_list args2 ); 00259 void process_line_buffer(); 00260 00261 std::vector< char > lineBuffer; 00262 00263 inline bool check( unsigned verbosity ) 00264 { 00265 return verbosity <= verbosityLimit; 00266 } 00267 }; 00268 00269 class DebugOutputStream 00270 { 00271 protected: 00272 friend class DebugOutput; 00273 int referenceCount; 00274 00275 public: 00276 DebugOutputStream() : referenceCount( 1 ) {} 00277 virtual ~DebugOutputStream(); 00278 virtual void println( const char* pfx, const char* str ) = 0; 00279 virtual void println( int rank, const char* pfx, const char* str ) = 0; 00280 }; 00281 00282 void DebugOutput::printf( int verbosity, const char* fmt, ... ) 00283 { 00284 if( check( verbosity ) ) 00285 { 00286 va_list args1, args2; 00287 va_start( args1, fmt ); 00288 va_start( args2, fmt ); 00289 print_real( fmt, args1, args2 ); 00290 va_end( args2 ); 00291 va_end( args1 ); 00292 } 00293 } 00294 00295 void DebugOutput::tprintf( int verbosity, const char* fmt, ... ) 00296 { 00297 if( check( verbosity ) ) 00298 { 00299 va_list args1, args2; 00300 va_start( args1, fmt ); 00301 va_start( args2, fmt ); 00302 tprint_real( fmt, args1, args2 ); 00303 va_end( args2 ); 00304 va_end( args1 ); 00305 } 00306 } 00307 00308 } // namespace moab 00309 00310 #endif