SUNphi  1.0
Logger.hpp
Go to the documentation of this file.
1 #ifndef _LOGGER_HPP
2 #define _LOGGER_HPP
3 
4 /// \file Logger.hpp
5 ///
6 /// \brief Header file to define a logger wrapping FILE*
7 ///
8 /// The internal class is used to really print, while the external one
9 /// to determine whether to print or not, and to lock in case the
10 /// threads are present. If printing is not needed, a fake internal
11 /// logger is passed, printing on /dev/null
12 ///
13 /// If threads are running, and all threads are allowed to print, the
14 /// Logger is locked so that only one thread at the time can print,
15 /// and all lines are prepended with thread id indication.
16 ///
17 /// If MPI is running, and all ranks are allowed, to print, each line
18 /// is prepended with the rank id. No cross-ranks lock is issued.
19 
20 #include <cstdio>
21 
22 #include <Threads.hpp>
23 #include <debug/BackTracing.hpp>
24 #include <debug/Crash.hpp>
25 #include <ios/File.hpp>
26 #include <ios/TextFormat.hpp>
27 #include <system/Mpi.hpp>
28 #include <system/Timer.hpp>
29 #include <utility/Macros.hpp>
30 #include <utility/ScopeDoer.hpp>
31 
32 namespace SUNphi
33 {
34  /// Write output to a file, using different level of indentation
35  class Logger :
36  private File
37  {
38  /// Fake logger, printing to /dev/null
40 
41  /// Access to the logger as if it was a file
42  const File& file()
43  const
44  {
45  return
46  static_cast<const File&>(*this);
47  }
48 
50 
51  /// Single line in the logger
52  class LoggerLine
53  {
54  /// Store wether the line has to be ended or not
56 
57  /// Store whether the line is crashing
58  bool hasToCrash;
59 
60  /// Mark that the color has changed in this line
62 
63  /// Mark that the style has changed in this line
65 
66  /// Check whether should actually print or not
67  const bool reallyPrint;
68 
69  /// Check if some other rank could be printing
71 
72  /// Check if some other thread could be printing
74 
75  /// Check whether we need to lock
76  const bool hasToLock;
77 
78  /// Reference to the logger
80 
81  /// Forbids copying a line
82  LoggerLine(const LoggerLine&)=delete;
83 
84  public:
85 
86  /// Starts a new line
87  void startNewLine()
88  {
89  /// Total number of the character written
90  int rc=
91  0;
92 
93  // Prepend with time
95  {
97  SCOPE_REAL_PRECISION(logger,10);
100  rc+=
101  (logger.file()<<durationInSec(timings.currentMeasure())<<" s").getRc();
102  }
103 
104  // Prepend with rank
105  if(someOtherRankCouldBePrinting)
106  rc+=
107  (logger.file()<<" Rank "<<mpi.rank()).getRc();
108 
109  // Prepend with thread
110  if(someOtherThreadCouldBePrinting)
111  rc+=
112  (logger.file()<<" Thread "<<threads.getThreadId()).getRc();
113 
114  // Mark the margin
115  if(rc)
116  logger.file()<<":\t";
117 
118  // Writes the given number of spaces
119  for(int i=0;i<logger.indentLev;i++)
120  logger.file()<<' ';
121  }
122 
123  /// Construct
125  : hasToEndLine(true),
126  hasToCrash(false),
127  colorChanged(false),
128  styleChanged(false),
134  {
135 
136  if(hasToLock)
137  logger.getExclusiveAccess();
138 
140  }
141 
142  /// Move constructor
144  : hasToEndLine(true),
151  hasToLock(oth.hasToLock),
152  logger(oth.logger)
153  {
154  oth.hasToEndLine=
155  false;
156  }
157 
158  /// Ends the line
159  void endLine()
160  {
161  logger.file()<<'\n';
162  }
163 
164  /// Destroy (end the line)
166  {
167  // Wrap everything here
168  if(hasToEndLine)
169  {
170  // Ends the quoted text
171  if(hasToCrash)
172  *this<<"\"";
173 
174  // Reset color
175  if(colorChanged)
176  *this<<TextColor::DEFAULT;
177 
178  // Reset style
179  if(styleChanged)
180  *this<<TextStyle::RESET;
181 
182  // Ends the line
183  endLine();
184 
185  if(hasToLock)
187 
188  if(hasToCrash)
189  {
191  exit(1);
192  }
193  }
194  }
195 
196  /// Prints after putting a space
197  template <typename T> // Type of the obected to print
198  LoggerLine& operator*(T&& t) ///< Object to be printed
199  {
200  logger.file()*forw<T>(t);
201 
202  return
203  *this;
204  }
205 
206  /// Catch-all print
207  ///
208  /// The SFINAE is needed to avoid that the method is used when
209  /// File does not know how to print
210  template <typename T, // Type of the quantity to print
211  typename=EnableIf<not canPrint<LoggerLine,T>>, // SFINAE needed to avoid ambiguous overload
212  typename=EnableIf<canPrint<File,const T&>>> // SFINAE needed to avoid ambiguous overload
213  LoggerLine& operator<<(const T& t) ///< Object to print
214  {
215  logger.file()<<t;
216 
217  return
218  *this;
219  }
220 
221  /// Print a C-style variadic message
222  LoggerLine& printVariadicMessage(const char* format, ///< Format to print
223  va_list ap) ///< Variadic part
224  {
226 
227  return
228  *this;
229  }
230 
231  /// Changes the color of the line
233  {
234  colorChanged=
235  true;
236 
237  return
238  *this<<
240  static_cast<char>(c)<<
242  }
243 
244  /// Changes the style of the line
246  {
247  styleChanged=
248  true;
249 
250  return
251  *this<<
253  static_cast<char>(c)<<
255  }
256 
257  /// Prints crash information
258  ///
259  /// Then sets the flag \c hasToCrash to true, such that at
260  /// destroy of the line, crash happens
262  {
263  this->hasToCrash=
264  true;
265 
266  (*this)<<TextColor::RED<<" ERROR in function "<<cr.getFuncName()<<" at line "<<cr.getLine()<<" of file "<<cr.getPath()<<": \"";
267 
268  return
269  *this;
270  }
271 
272  /// Prints a string, parsing newline
273  LoggerLine& operator<<(const char* str)
274  {
275  if(str==nullptr)
276  logger.file()<<str;
277  else
278  {
279  /// Pointer to the first char of the string
280  const char* p=
281  str;
282 
283  // Prints until finding end of string
284  while(*p!='\0')
285  {
286  // starts a new line
287  if(*p=='\n')
288  {
289  endLine();
290  startNewLine();
291  }
292  else
293  // Prints the char
294  *this<<*p;
295 
296  // Increment the char
297  p++;
298  }
299  }
300 
301  return
302  *this;
303  }
304 
305  /// Prints a c++ string
307  {
308  return
309  *this<<str.c_str();
310  }
311 
312  };
313 
314  /// Indentation level
315  int indentLev{0};
316 
317  /// Determine wheter the new line includes time
319 
320  /// Mutex used to lock the logger
321  mutable Mutex mutex;
322 
323  /// Set the exclusive access right
325  {
326  mutex.lock();
327  }
328 
329  /// Release the exclusive access right
331  {
332  mutex.unlock();
333  }
334 
335  public:
336 
337  using File::alwaysPrintSign;
338  using File::alwaysPrintZero;
339  using File::realFormat;
340  using File::realPrecision;
341 
342  /// Decide whether only master thread can write here
344 
345  /// Decide whether only master MPI can write here
347 
348  /////////////////////////////////////////////////////////////////
349 
350  /// Increase indentation
351  void indentMore()
352  {
353  indentLev++;
354  }
355 
356  /// Decrease indentation
357  void indentLess()
358  {
359  indentLev--;
360  }
361 
362  /// Create a new line
364  {
365  return
366  *this;
367  }
368 
369  /// Create a new line
371  {
372  return
373  *this;
374  }
375  // /// Create a new line, and print on it
376  // template <typename T,
377  // typename=EnableIf<canPrint<LoggerLine,T>>, // SFINAE needed to avoid ambiguous overload
378  // typename=EnableIf<not canPrint<Logger,RemRef<T>>>> // SFINAE to avoid ambiguous reimplementation
379  // LoggerLine operator<<(T&& t)
380  // {
381  // return
382  // std::move(getNewLine()<<forw<T>(t));
383  // }
384 
385  /// Print a C-style variadic message
386  LoggerLine printVariadicMessage(const char* format, ///< Format to print
387  va_list ap) ///< Variadic part
388  {
389  return
390  std::move(getNewLine().printVariadicMessage(format,ap));
391  }
392 
393  /// Create with a path
394  Logger(const char* path, ///< Path to open
395  const bool& prependTime=true) ///< Prepend or not with time
396  :
397  prependTime(prependTime)
398  {
399  file().open(path,"w");
400 
401  // Cannot print, otherwise all rank would!
402  //*this<<"Logger initialized";
403  }
404  };
405 
406  /// Increment the logger indentation level for the object scope
408  {
409  /// Pointed logger
411 
412  public:
413 
414  /// Create and increase indent level
416  logger(logger)
417  {
418  logger.indentMore();
419  }
420 
421  /// Delete and decrease indent level
423  {
425  }
426  };
427 
428  extern Logger runLog;
429 }
430 
431 /// Create the line
432 #define RUNLOG
433  runLog()
434 
435 
436 #endif
#define SCOPE_NOT_ALWAYS_PUT_SIGN(STREAM)
Set not to print always sign at the beginning of a number for current scope.
Definition: File.hpp:49
LoggerLine printVariadicMessage(const char *format, va_list ap)
Print a C-style variadic message.
Definition: Logger.hpp:386
LoggerLine getNewLine()
Create a new line.
Definition: Logger.hpp:363
Logger & logger
Reference to the logger.
Definition: Logger.hpp:79
static Logger fakeLogger
Fake logger, printing to /dev/null.
Definition: Logger.hpp:39
const bool reallyPrint
Check whether should actually print or not.
Definition: Logger.hpp:67
LoggerLine(LoggerLine &&oth)
Move constructor.
Definition: Logger.hpp:143
bool colorChanged
Mark that the color has changed in this line.
Definition: Logger.hpp:61
void printBacktraceList()
Write the list of called routines.
Definition: BackTracing.cpp:16
~ScopeIndenter()
Delete and decrease indent level.
Definition: Logger.hpp:422
LoggerLine & operator*(T &&t)
Prints after putting a space.
Definition: Logger.hpp:198
bool styleChanged
Mark that the style has changed in this line.
Definition: Logger.hpp:64
bool hasToEndLine
Store wether the line has to be ended or not.
Definition: Logger.hpp:55
void indentMore()
Increase indentation.
Definition: Logger.hpp:351
const bool hasToLock
Check whether we need to lock.
Definition: Logger.hpp:76
File & operator<<(const uint64_t &l)
Prints a long unsigned integer.
Definition: File.hpp:193
ScopeIndenter(Logger &logger)
Create and increase indent level.
Definition: Logger.hpp:415
Logger(const char *path, const bool &prependTime=true)
Create with a path.
Definition: Logger.hpp:394
Mutex mutex
Mutex used to lock the logger.
Definition: Logger.hpp:321
bool prependTime
Determine wheter the new line includes time.
Definition: Logger.hpp:318
Increment the logger indentation level for the object scope.
Definition: Logger.hpp:407
void endLine()
Ends the line.
Definition: Logger.hpp:159
Logger runLog("/dev/stdout")
Global logger.
bool hasToCrash
Store whether the line is crashing.
Definition: Logger.hpp:58
const bool someOtherRankCouldBePrinting
Check if some other rank could be printing.
Definition: Logger.hpp:70
~LoggerLine()
Destroy (end the line)
Definition: Logger.hpp:165
LoggerLine & operator<<(const std::string &str)
Prints a c++ string.
Definition: Logger.hpp:306
void releaseExclusiveAccess()
Release the exclusive access right.
Definition: Logger.hpp:330
#define SCOPE_REAL_PRECISION(STREAM, VAL)
Set the precision for current scope.
Definition: File.hpp:25
LoggerLine(const LoggerLine &)=delete
Forbids copying a line.
decltype(auto) file(Ts &&...ts)
Definition: Logger.hpp:49
#define SCOPE_ALWAYS_PRINT_ZERO(STREAM)
Set printing or not zero.
Definition: File.hpp:57
#define PROVIDE_ALSO_NON_CONST_METHOD(NAME)
Definition: TypeTraits.hpp:376
#define SCOPE_REAL_FORMAT_FIXED(STREAM)
Set fixed for the current scope.
Definition: File.hpp:37
const bool someOtherThreadCouldBePrinting
Check if some other thread could be printing.
Definition: Logger.hpp:73
const File & file() const
Access to the logger as if it was a file.
Definition: Logger.hpp:42
void getExclusiveAccess()
Set the exclusive access right.
Definition: Logger.hpp:324
LoggerLine operator()()
Create a new line.
Definition: Logger.hpp:370
Logger & logger
Pointed logger.
Definition: Logger.hpp:410
void indentLess()
Decrease indentation.
Definition: Logger.hpp:357
LoggerLine(Logger &logger)
Construct.
Definition: Logger.hpp:124
void startNewLine()
Starts a new line.
Definition: Logger.hpp:87