Caffe2 - C++ API
A deep learning, cross platform ML framework
logging.h
1 #ifndef CAFFE2_CORE_LOGGING_H_
2 #define CAFFE2_CORE_LOGGING_H_
3 
4 #include <climits>
5 #include <exception>
6 #include <functional>
7 #include <limits>
8 #include <sstream>
9 
10 #include "caffe2/core/flags.h"
11 #include "caffe2/proto/caffe2.pb.h"
12 
13 // CAFFE2_LOG_THRESHOLD is a compile time flag that would allow us to turn off
14 // logging at compile time so no logging message below that level is produced
15 // at all. The value should be between INT_MIN and CAFFE_FATAL.
16 #ifndef CAFFE2_LOG_THRESHOLD
17 // If we have not defined the compile time log threshold, we keep all the
18 // log cases.
19 #define CAFFE2_LOG_THRESHOLD INT_MIN
20 #endif // CAFFE2_LOG_THRESHOLD
21 
22 // Below are different implementations for glog and non-glog cases.
23 #ifdef CAFFE2_USE_GOOGLE_GLOG
24 #include "caffe2/core/logging_is_google_glog.h"
25 #else // !CAFFE2_USE_GOOGLE_GLOG
26 #include "caffe2/core/logging_is_not_google_glog.h"
27 #endif // CAFFE2_USE_GOOGLE_GLOG
28 
29 CAFFE2_DECLARE_int(caffe2_log_level);
30 CAFFE2_DECLARE_bool(caffe2_use_fatal_for_enforce);
31 
32 namespace caffe2 {
33 // Functions that we use for initialization.
34 bool InitCaffeLogging(int* argc, char** argv);
35 
36 constexpr bool IsUsingGoogleLogging() {
37 #ifdef CAFFE2_USE_GOOGLE_GLOG
38  return true;
39 #else
40  return false;
41 #endif
42 }
43 
44 inline void MakeStringInternal(std::stringstream& ss) {}
45 
46 template <typename T>
47 inline void MakeStringInternal(std::stringstream& ss, const T& t) {
48  ss << t;
49 }
50 
51 template <typename T, typename... Args>
52 inline void
53 MakeStringInternal(std::stringstream& ss, const T& t, const Args&... args) {
54  MakeStringInternal(ss, t);
55  MakeStringInternal(ss, args...);
56 }
57 
58 template <typename... Args>
59 string MakeString(const Args&... args) {
60  std::stringstream ss;
61  MakeStringInternal(ss, args...);
62  return string(ss.str());
63 }
64 
65 // Specializations for already-a-string types.
66 template <>
67 inline string MakeString(const string& str) {
68  return str;
69 }
70 inline string MakeString(const char* c_str) {
71  return string(c_str);
72 }
73 
74 template <class Container>
75 inline string Join(const string& delimiter, const Container& v) {
76  std::stringstream s;
77  int cnt = static_cast<int64_t>(v.size()) - 1;
78  for (auto i = v.begin(); i != v.end(); ++i, --cnt) {
79  s << (*i) << (cnt ? delimiter : "");
80  }
81  return s.str();
82 }
83 
84 // Obtains the base name from a full path.
85 string StripBasename(const std::string& full_path);
86 
87 // Replace all occurrences of "from" substring to "to" string.
88 // Returns number of replacements
89 size_t ReplaceAll(string& s, const char* from, const char* to);
90 
91 void SetStackTraceFetcher(std::function<string(void)> fetcher);
92 
93 void SetOperatorLogger(std::function<void(const OperatorDef&)> tracer);
94 std::function<void(const OperatorDef&)> GetOperatorLogger();
95 
96 class EnforceNotMet : public std::exception {
97  public:
99  const char* file,
100  const int line,
101  const char* condition,
102  const string& msg,
103  const void* caller=nullptr);
104  void AppendMessage(const string& msg);
105  string msg() const;
106  inline const vector<string>& msg_stack() const {
107  return msg_stack_;
108  }
109 
110  const char* what() const noexcept override;
111 
112  const void* caller() const noexcept;
113 
114  private:
115  vector<string> msg_stack_;
116  string full_msg_;
117  string stack_trace_;
118  const void* caller_;
119 };
120 
121 #define CAFFE_ENFORCE(condition, ...) \
122  do { \
123  if (!(condition)) { \
124  throw ::caffe2::EnforceNotMet( \
125  __FILE__, __LINE__, #condition, ::caffe2::MakeString(__VA_ARGS__)); \
126  } \
127  } while (false)
128 
129 #define CAFFE_ENFORCE_WITH_CALLER(condition, ...) \
130  do { \
131  if (!(condition)) { \
132  throw ::caffe2::EnforceNotMet( \
133  __FILE__, __LINE__, #condition, ::caffe2::MakeString(__VA_ARGS__), this); \
134  } \
135  } while (false)
136 
137 #define CAFFE_THROW(...) \
138  throw ::caffe2::EnforceNotMet( \
139  __FILE__, __LINE__, "", ::caffe2::MakeString(__VA_ARGS__))
140 
168 namespace enforce_detail {
169 
170 struct EnforceOK {};
171 
173  public:
174 #ifdef _MSC_VER
175  // MSVC + NVCC ignores constexpr and will issue a warning if included.
176  /* implicit */ EnforceFailMessage(EnforceOK) : msg_(nullptr) {}
177 #else
178  constexpr /* implicit */ EnforceFailMessage(EnforceOK) : msg_(nullptr) {}
179 #endif
180  EnforceFailMessage(EnforceFailMessage&&) = default;
181  EnforceFailMessage(const EnforceFailMessage&) = delete;
182  EnforceFailMessage& operator=(EnforceFailMessage&&) = delete;
183  EnforceFailMessage& operator=(const EnforceFailMessage&) = delete;
184 
185  // Catch all wrong usages like CAFFE_ENFORCE_THAT(x < y)
186  template <class... Args>
187  /* implicit */ EnforceFailMessage(Args...) {
188  static_assert(
189  // This stands for an "impossible" condition. Plain `false` doesn't
190  // trick compiler enough.
191  sizeof...(Args) == std::numeric_limits<std::size_t>::max(),
192  "CAFFE_ENFORCE_THAT has to be used with one of special check functions "
193  "like `Equals`. Use CAFFE_ENFORCE for simple boolean checks.");
194  }
195 
196  /* implicit */ EnforceFailMessage(std::string&& msg) {
197  msg_ = new std::string(std::move(msg));
198  }
199  inline bool bad() const {
200  return msg_ != nullptr;
201  }
202  std::string get_message_and_free(std::string&& extra) const {
203  std::string r;
204  if (extra.empty()) {
205  r = std::move(*msg_);
206  } else {
207  r = ::caffe2::MakeString(std::move(*msg_), ". ", std::move(extra));
208  }
209  delete msg_;
210  return r;
211  }
212 
213  private:
214  std::string* msg_;
215 };
216 
217 #define BINARY_COMP_HELPER(name, op) \
218  template <typename T1, typename T2> \
219  inline EnforceFailMessage name(const T1& x, const T2& y) { \
220  if (x op y) { \
221  return EnforceOK(); \
222  } \
223  return MakeString(x, " vs ", y); \
224  }
225 BINARY_COMP_HELPER(Equals, ==)
226 BINARY_COMP_HELPER(NotEquals, !=)
227 BINARY_COMP_HELPER(Greater, >)
228 BINARY_COMP_HELPER(GreaterEquals, >=)
229 BINARY_COMP_HELPER(Less, <)
230 BINARY_COMP_HELPER(LessEquals, <=)
231 #undef BINARY_COMP_HELPER
232 
233 #define CAFFE_ENFORCE_THAT_IMPL(condition, expr, ...) \
234  do { \
235  using namespace ::caffe2::enforce_detail; \
236  const EnforceFailMessage& r = (condition); \
237  if (r.bad()) { \
238  throw ::caffe2::EnforceNotMet( \
239  __FILE__, \
240  __LINE__, \
241  expr, \
242  r.get_message_and_free(::caffe2::MakeString(__VA_ARGS__))); \
243  } \
244  } while (false)
245 }
246 
247 #define CAFFE_ENFORCE_THAT(condition, ...) \
248  CAFFE_ENFORCE_THAT_IMPL((condition), #condition, __VA_ARGS__)
249 
250 #define CAFFE_ENFORCE_EQ(x, y, ...) \
251  CAFFE_ENFORCE_THAT_IMPL(Equals((x), (y)), #x " == " #y, __VA_ARGS__)
252 #define CAFFE_ENFORCE_NE(x, y, ...) \
253  CAFFE_ENFORCE_THAT_IMPL(NotEquals((x), (y)), #x " != " #y, __VA_ARGS__)
254 #define CAFFE_ENFORCE_LE(x, y, ...) \
255  CAFFE_ENFORCE_THAT_IMPL(LessEquals((x), (y)), #x " <= " #y, __VA_ARGS__)
256 #define CAFFE_ENFORCE_LT(x, y, ...) \
257  CAFFE_ENFORCE_THAT_IMPL(Less((x), (y)), #x " < " #y, __VA_ARGS__)
258 #define CAFFE_ENFORCE_GE(x, y, ...) \
259  CAFFE_ENFORCE_THAT_IMPL(GreaterEquals((x), (y)), #x " >= " #y, __VA_ARGS__)
260 #define CAFFE_ENFORCE_GT(x, y, ...) \
261  CAFFE_ENFORCE_THAT_IMPL(Greater((x), (y)), #x " > " #y, __VA_ARGS__)
262 
263 } // namespace caffe2
264 
265 #endif // CAFFE2_CORE_LOGGING_H_
Simple registry implementation in Caffe2 that uses static variables to register object creators durin...
Commandline flags support for Caffe2.