Caffe2 - C++ API
A deep learning, cross platform ML framework
logging_is_not_google_glog.h
1 #ifndef CAFFE2_CORE_LOGGING_IS_NOT_GOOGLE_GLOG_H_
2 #define CAFFE2_CORE_LOGGING_IS_NOT_GOOGLE_GLOG_H_
3 
4 #include <chrono>
5 #include <climits>
6 #include <ctime>
7 #include <iomanip>
8 #include <string>
9 #include <fstream>
10 #include <set>
11 #include <sstream>
12 #include <vector>
13 
14 #include "caffe2/core/flags.h"
15 
16 // Log severity level constants.
17 const int FATAL = 3;
18 #if !defined(_MSC_VER) || !defined(ERROR)
19 // Windows defines the ERROR macro already, and as a result we will
20 // simply use that one. The downside is that one will now mix LOG(INFO)
21 // and LOG(ERROR) because ERROR is defined to be zero. Anyway, the
22 // recommended way is to use glog so fixing this is a low-pri item.
23 const int ERROR = 2;
24 #endif
25 const int WARNING = 1;
26 const int INFO = 0;
27 const char CAFFE2_SEVERITY_PREFIX[] = "FEWIV";
28 
29 namespace caffe2 {
31  public:
32  MessageLogger(const char *file, int line, int severity);
33  ~MessageLogger();
34  // Return the stream associated with the logger object.
35  std::stringstream &stream() { return stream_; }
36 
37  private:
38  // When there is a fatal log, we simply abort.
39  void DealWithFatal() { abort(); }
40 
41  const char* tag_;
42  std::stringstream stream_;
43  int severity_;
44 };
45 
46 // This class is used to explicitly ignore values in the conditional
47 // logging macros. This avoids compiler warnings like "value computed
48 // is not used" and "statement has no effect".
50  public:
51  LoggerVoidify() { }
52  // This has to be an operator with a precedence lower than << but
53  // higher than ?:
54  void operator&(const std::ostream &s) { }
55 };
56 
57 // Log a message and terminate.
58 template<class T>
59 void LogMessageFatal(const char *file, int line, const T &message) {
60  MessageLogger(file, line, FATAL).stream() << message;
61 }
62 
63 // Helpers for CHECK_NOTNULL(). Two are necessary to support both raw pointers
64 // and smart pointers.
65 template <typename T>
66 T& CheckNotNullCommon(const char *file, int line, const char *names, T& t) {
67  if (t == nullptr) {
68  LogMessageFatal(file, line, std::string(names));
69  }
70  return t;
71 }
72 
73 template <typename T>
74 T* CheckNotNull(const char *file, int line, const char *names, T* t) {
75  return CheckNotNullCommon(file, line, names, t);
76 }
77 
78 template <typename T>
79 T& CheckNotNull(const char *file, int line, const char *names, T& t) {
80  return CheckNotNullCommon(file, line, names, t);
81 }
82 } // namespace caffe2
83 
84 // ---------------------- Logging Macro definitions --------------------------
85 
86 
87 static_assert(CAFFE2_LOG_THRESHOLD <= FATAL,
88  "CAFFE2_LOG_THRESHOLD should at most be FATAL.");
89 // If n is under the compile time caffe log threshold, The _CAFFE_LOG(n)
90 // should not generate anything in optimized code.
91 #define LOG(n) \
92  if (n >= CAFFE2_LOG_THRESHOLD) \
93  ::caffe2::MessageLogger((char*)__FILE__, __LINE__, n).stream()
94 #define VLOG(n) LOG((-n))
95 
96 #define LOG_IF(n, condition) \
97  if (n >= CAFFE2_LOG_THRESHOLD && (condition)) \
98  ::caffe2::MessageLogger((char*)__FILE__, __LINE__, n).stream()
99 #define VLOG_IF(n, condition) LOG_IF((-n), (condition))
100 
101 #define VLOG_IS_ON(verboselevel) (CAFFE2_LOG_THRESHOLD <= -(verboselevel))
102 
103 // Log only if condition is met. Otherwise evaluates to void.
104 #define FATAL_IF(condition) \
105  condition ? (void) 0 : ::caffe2::LoggerVoidify() & \
106  ::caffe2::MessageLogger((char*)__FILE__, __LINE__, FATAL).stream()
107 
108 // Check for a given boolean condition.
109 #define CHECK(condition) FATAL_IF(condition) \
110  << "Check failed: " #condition " "
111 
112 #ifndef NDEBUG
113 // Debug only version of CHECK
114 #define DCHECK(condition) FATAL_IF(condition) \
115  << "Check failed: " #condition " "
116 #else
117 // Optimized version - generates no code.
118 #define DCHECK(condition) if(false) CHECK(condition)
119 #endif // NDEBUG
120 
121 #define CHECK_OP(val1, val2, op) FATAL_IF((val1 op val2)) \
122  << "Check failed: " #val1 " " #op " " #val2 " "
123 
124 // Check_op macro definitions
125 #define CHECK_EQ(val1, val2) CHECK_OP(val1, val2, ==)
126 #define CHECK_NE(val1, val2) CHECK_OP(val1, val2, !=)
127 #define CHECK_LE(val1, val2) CHECK_OP(val1, val2, <=)
128 #define CHECK_LT(val1, val2) CHECK_OP(val1, val2, <)
129 #define CHECK_GE(val1, val2) CHECK_OP(val1, val2, >=)
130 #define CHECK_GT(val1, val2) CHECK_OP(val1, val2, >)
131 
132 #ifndef NDEBUG
133 // Debug only versions of CHECK_OP macros.
134 #define DCHECK_EQ(val1, val2) CHECK_OP(val1, val2, ==)
135 #define DCHECK_NE(val1, val2) CHECK_OP(val1, val2, !=)
136 #define DCHECK_LE(val1, val2) CHECK_OP(val1, val2, <=)
137 #define DCHECK_LT(val1, val2) CHECK_OP(val1, val2, <)
138 #define DCHECK_GE(val1, val2) CHECK_OP(val1, val2, >=)
139 #define DCHECK_GT(val1, val2) CHECK_OP(val1, val2, >)
140 #else // !NDEBUG
141 // These versions generate no code in optimized mode.
142 #define DCHECK_EQ(val1, val2) if(false) CHECK_OP(val1, val2, ==)
143 #define DCHECK_NE(val1, val2) if(false) CHECK_OP(val1, val2, !=)
144 #define DCHECK_LE(val1, val2) if(false) CHECK_OP(val1, val2, <=)
145 #define DCHECK_LT(val1, val2) if(false) CHECK_OP(val1, val2, <)
146 #define DCHECK_GE(val1, val2) if(false) CHECK_OP(val1, val2, >=)
147 #define DCHECK_GT(val1, val2) if(false) CHECK_OP(val1, val2, >)
148 #endif // NDEBUG
149 
150 // Check that a pointer is not null.
151 #define CHECK_NOTNULL(val) \
152  ::caffe2::CheckNotNull( \
153  __FILE__, __LINE__, "Check failed: '" #val "' Must be non NULL", (val))
154 
155 #ifndef NDEBUG
156 // Debug only version of CHECK_NOTNULL
157 #define DCHECK_NOTNULL(val) \
158  ::caffe2::CheckNotNull( \
159  __FILE__, __LINE__, "Check failed: '" #val "' Must be non NULL", (val))
160 #else // !NDEBUG
161 // Optimized version - generates no code.
162 #define DCHECK_NOTNULL(val) if (false) CHECK_NOTNULL(val)
163 #endif // NDEBUG
164 
165 // ---------------------- Support for std objects --------------------------
166 // These are adapted from glog to support a limited set of logging capability
167 // for STL objects.
168 
169 namespace caffe2 {
170 // Forward declare these two, and define them after all the container streams
171 // operators so that we can recurse from pair -> container -> container -> pair
172 // properly.
173 template<class First, class Second>
174 std::ostream& operator<<(
175  std::ostream& out, const std::pair<First, Second>& p);
176 template <class Iter>
177 void PrintSequence(std::ostream& ss, Iter begin, Iter end);
178 
179 #define INSTANTIATE_FOR_CONTAINER(container) \
180 template <class... Types> \
181 std::ostream& operator<<( \
182  std::ostream& out, const container<Types...>& seq) { \
183  PrintSequence(out, seq.begin(), seq.end()); \
184  return out; \
185 }
186 
187 INSTANTIATE_FOR_CONTAINER(std::vector)
188 INSTANTIATE_FOR_CONTAINER(std::map)
189 INSTANTIATE_FOR_CONTAINER(std::set)
190 #undef INSTANTIATE_FOR_CONTAINER
191 
192 template<class First, class Second>
193 inline std::ostream& operator<<(
194  std::ostream& out, const std::pair<First, Second>& p) {
195  out << '(' << p.first << ", " << p.second << ')';
196  return out;
197 }
198 
199 template <class Iter>
200 inline void PrintSequence(std::ostream& out, Iter begin, Iter end) {
201  // Output at most 100 elements -- appropriate if used for logging.
202  for (int i = 0; begin != end && i < 100; ++i, ++begin) {
203  if (i > 0) out << ' ';
204  out << *begin;
205  }
206  if (begin != end) {
207  out << " ...";
208  }
209 }
210 } // namespace caffe2
211 
212 #endif // CAFFE2_CORE_LOGGING_IS_NOT_GOOGLE_GLOG_H_
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
Commandline flags support for Caffe2.