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