MOAB: Mesh Oriented datABase  (version 5.4.1)
DebugOutput.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines