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