Branch data Line data Source code
1 : : #ifndef moab_DEBUG_OUTPUT_HPP
2 : : #define moab_DEBUG_OUTPUT_HPP
3 : :
4 : : #include <stdarg.h>
5 : : #include <stdio.h>
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 : : */
43 : : class DebugOutput
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 : 0 : bool have_rank() const
132 : : {
133 : 0 : return mpiRank >= 0;
134 : : }
135 : : //!\brief Get MPI rank.
136 : 0 : int get_rank() const
137 : : {
138 : 0 : return mpiRank;
139 : : }
140 : : //!\brief Set MPI rank.
141 : 66 : void set_rank( int rank )
142 : : {
143 : 66 : mpiRank = rank;
144 : 66 : }
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
150 : 69 : void limit_output_to_first_N_procs( int N )
151 : : {
152 [ - + ]: 69 : if( mpiRank >= N ) verbosityLimit = 0;
153 : 69 : }
154 : :
155 : : //!\brief Get verbosity limit
156 : 20 : unsigned get_verbosity() const
157 : : {
158 : 20 : return verbosityLimit;
159 : : }
160 : : //!\brief Set verbosity limit
161 : 0 : void set_verbosity( unsigned val )
162 : : {
163 : 0 : verbosityLimit = val;
164 : 0 : }
165 : :
166 : : //!\brief Get line prefix
167 : : const std::string& get_prefix() const
168 : : {
169 : : return linePfx;
170 : : }
171 : : //!\brief Set line prefix
172 : 0 : void set_prefix( const std::string& str )
173 : : {
174 : 0 : linePfx = str;
175 : 0 : }
176 : :
177 : : //!\brief Output the specified string iff output is enabled.
178 : 576 : void print( int verbosity, const char* str )
179 : : {
180 [ - + ]: 576 : if( check( verbosity ) ) print_real( str );
181 : 576 : }
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 : 1073 : void tprint( int verbosity, const char* str )
196 : : {
197 [ - + ]: 1073 : if( check( verbosity ) ) tprint_real( str );
198 : 1073 : }
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 : 245 : void print( int verbosity, const char* pfx, const Range& range )
216 : : {
217 [ - + ]: 245 : if( check( verbosity ) ) list_range_real( pfx, range );
218 : 245 : }
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 : 0 : void print_ints( int verbosity, const char* pfx, const Range& range )
228 : : {
229 [ # # ]: 0 : if( check( verbosity ) ) list_ints_real( pfx, range );
230 : 0 : }
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;
239 : : DebugOutputStream* outputImpl;
240 : : int mpiRank;
241 : : unsigned verbosityLimit;
242 : : CpuTimer cpuTi;
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 : 8843 : inline bool check( unsigned verbosity )
264 : : {
265 : 8843 : return verbosity <= verbosityLimit;
266 : : }
267 : : };
268 : :
269 : : class DebugOutputStream
270 : : {
271 : : protected:
272 : : friend class DebugOutput;
273 : : int referenceCount;
274 : :
275 : : public:
276 : 175 : DebugOutputStream() : referenceCount( 1 ) {}
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 : 5749 : void DebugOutput::printf( int verbosity, const char* fmt, ... )
283 : : {
284 [ - + ]: 5749 : if( check( verbosity ) )
285 : : {
286 : : va_list args1, args2;
287 : 0 : va_start( args1, fmt );
288 : 0 : va_start( args2, fmt );
289 [ # # ]: 0 : print_real( fmt, args1, args2 );
290 : 0 : va_end( args2 );
291 : 0 : va_end( args1 );
292 : : }
293 : 5749 : }
294 : :
295 : 1200 : void DebugOutput::tprintf( int verbosity, const char* fmt, ... )
296 : : {
297 [ - + ]: 1200 : if( check( verbosity ) )
298 : : {
299 : : va_list args1, args2;
300 : 0 : va_start( args1, fmt );
301 : 0 : va_start( args2, fmt );
302 [ # # ]: 0 : tprint_real( fmt, args1, args2 );
303 : 0 : va_end( args2 );
304 : 0 : va_end( args1 );
305 : : }
306 : 1200 : }
307 : :
308 : : } // namespace moab
309 : :
310 : : #endif
|