kaldi-error.h 5.91 KB
Newer Older
1 2
// base/kaldi-error.h

Arnab Ghoshal's avatar
Arnab Ghoshal committed
3 4
// Copyright 2009-2011  Microsoft Corporation;  Ondrej Glembek;  Lukas Burget;
//                      Saarland University
5

6 7
// See ../../COPYING for clarification regarding multiple authors
//
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
// MERCHANTABLITY OR NON-INFRINGEMENT.
// See the Apache 2 License for the specific language governing permissions and
// limitations under the License.

#ifndef KALDI_BASE_KALDI_ERROR_H_
#define KALDI_BASE_KALDI_ERROR_H_ 1

#include <stdexcept>
#include <string>
Karel Vesely's avatar
Karel Vesely committed
26
#include <cstring>
27
#include <sstream>
Karel Vesely's avatar
Karel Vesely committed
28
#include <cstdio>
29

30 31
#if _MSC_VER >= 1900 || (!defined(_MSC_VER) && __cplusplus >= 201103L) || defined(__GXX_EXPERIMENTAL_CXX0X__)
#define KALDI_NOEXCEPT(Predicate) noexcept((Predicate))
32
#else
33
#define KALDI_NOEXCEPT(Predicate)
34 35
#endif

36
#include "base/kaldi-types.h"
37
#include "base/kaldi-utils.h"
38 39 40 41 42 43 44 45 46 47 48 49

/* Important that this file does not depend on any other kaldi headers. */


namespace kaldi {

/// \addtogroup error_group
/// @{

/// This is set by util/parse-options.{h, cc} if you set --verbose = ? option
extern int32 g_kaldi_verbose_level;

Dan Povey's avatar
Dan Povey committed
50 51 52 53 54
/// This is set by util/parse-options.{h, cc} (from argv[0]) and used (if set)
/// in error reporting code to display the name of the program (this is because
/// in our scripts, we often mix together the stderr of many programs).  it is
/// the base-name of the program (no directory), followed by ':' We don't use
/// std::string, due to the static initialization order fiasco.
55
extern const char *g_program_name;
56 57 58

inline int32 GetVerboseLevel() { return g_kaldi_verbose_level; }

59 60 61 62
/// This should be rarely used; command-line programs set the verbose level
/// automatically from ParseOptions.
inline void SetVerboseLevel(int32 i) { g_kaldi_verbose_level = i; }

63
// Class KaldiLogMessage is invoked from the  KALDI_WARN, KALDI_VLOG and
64 65 66
// KALDI_LOG macros. It prints the message to stderr.  Note: we avoid
// using cerr, due to problems with thread safety.  fprintf is guaranteed
// thread-safe.
67 68 69 70

// class KaldiWarnMessage is invoked from the KALDI_WARN macro.
class KaldiWarnMessage {
 public:
71
  inline std::ostream &stream() { return ss; }
72
  KaldiWarnMessage(const char *func, const char *file, int32 line);
73 74 75
  ~KaldiWarnMessage()  { fprintf(stderr, "%s\n", ss.str().c_str()); }
 private:
  std::ostringstream ss;
76 77 78 79 80
};

// class KaldiLogMessage is invoked from the KALDI_LOG macro.
class KaldiLogMessage {
 public:
81
  inline std::ostream &stream() { return ss; }
82
  KaldiLogMessage(const char *func, const char *file, int32 line);
83 84 85
  ~KaldiLogMessage() { fprintf(stderr, "%s\n", ss.str().c_str()); }
 private:
  std::ostringstream ss;
86 87 88 89 90 91 92
};

// Class KaldiVlogMessage is invoked from the KALDI_VLOG macro.
class KaldiVlogMessage {
 public:
  KaldiVlogMessage(const char *func, const char *file, int32 line,
                   int32 verbose_level);
93 94 95 96
  inline std::ostream &stream() { return ss; }
  ~KaldiVlogMessage() { fprintf(stderr, "%s\n", ss.str().c_str()); }
 private:
  std::ostringstream ss;
97 98 99 100 101 102 103 104 105
};


// class KaldiErrorMessage is invoked from the KALDI_ERROR macro.
// The destructor throws an exception.
class KaldiErrorMessage {
 public:
  KaldiErrorMessage(const char *func, const char *file, int32 line);
  inline std::ostream &stream() { return ss; }
106
  ~KaldiErrorMessage() KALDI_NOEXCEPT(false);  // defined in kaldi-error.cc
107 108 109 110 111 112 113 114 115 116
 private:
  std::ostringstream ss;
};



#ifdef _MSC_VER
#define __func__ __FUNCTION__
#endif

117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
// Note on KALDI_ASSERT and KALDI_PARANOID_ASSERT
// The original (simple) version of the code was this
//
// #define KALDI_ASSERT(cond) if (!(cond)) kaldi::KaldiAssertFailure_(__func__, __FILE__, __LINE__, #cond);
//
// That worked well, but we were concerned that it
// could potentially cause a performance issue due to failed branch
// prediction (best practice is to have the if branch be the commonly
// taken one).
// Therefore, we decided to move the call into the else{} branch.
// A single block {} around if /else  does not work, because it causes 
// syntax error (unmatched else block) in the following code:
//
// if (condition)
//   KALDI_ASSERT(condition2);
// else
//   SomethingElse();
//
// do {} while(0)  -- note there is no semicolon at the end! --- works nicely
// and compilers will be able to optimize the loop away (as the condition
// is always false).
138 139
#ifndef NDEBUG
#define KALDI_ASSERT(cond) \
140
  do { if ((cond)) ; else kaldi::KaldiAssertFailure_(__func__, __FILE__, __LINE__, #cond);} while(0)
141 142 143
#else
#define KALDI_ASSERT(cond)
#endif
144 145 146 147 148
// also see KALDI_COMPILE_TIME_ASSERT, defined in base/kaldi-utils.h,
// and KALDI_ASSERT_IS_INTEGER_TYPE and KALDI_ASSERT_IS_FLOATING_TYPE,
// also defined there.
#ifdef KALDI_PARANOID // some more expensive asserts only checked if this defined
#define KALDI_PARANOID_ASSERT(cond) \
149
  do { if ((cond)) ; else kaldi::KaldiAssertFailure_(__func__, __FILE__, __LINE__, #cond);} while(0)
150 151 152
#else
#define KALDI_PARANOID_ASSERT(cond)
#endif
153

154

155 156 157
#define KALDI_ERR kaldi::KaldiErrorMessage(__func__, __FILE__, __LINE__).stream() 
#define KALDI_WARN kaldi::KaldiWarnMessage(__func__, __FILE__, __LINE__).stream() 
#define KALDI_LOG kaldi::KaldiLogMessage(__func__, __FILE__, __LINE__).stream()
158

159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
#define KALDI_VLOG(v) if (v <= kaldi::g_kaldi_verbose_level)     \
           kaldi::KaldiVlogMessage(__func__, __FILE__, __LINE__, v).stream()

inline bool IsKaldiError(const std::string &str) {
  return(!strncmp(str.c_str(), "ERROR ", 6));
}

void KaldiAssertFailure_(const char *func, const char *file,
                         int32 line, const char *cond_str);

/// @} end "addtogroup error_group"

}  // namespace kaldi

#endif  // KALDI_BASE_KALDI_ERROR_H_