#ifndef TENSORFLOW_PLATFORM_DEFAULT_LOGGING_H_ #define TENSORFLOW_PLATFORM_DEFAULT_LOGGING_H_ #include #include "tensorflow/core/platform/port.h" namespace tensorflow { const int INFO = 0; // base_logging::INFO; const int WARNING = 1; // base_logging::WARNING; const int ERROR = 2; // base_logging::ERROR; const int FATAL = 3; // base_logging::FATAL; const int NUM_SEVERITIES = 4; // base_logging::NUM_SEVERITIES; namespace internal { class LogMessage : public std::basic_ostringstream { public: LogMessage(const char* fname, int line, int severity); ~LogMessage(); protected: void GenerateLogMessage(); private: const char* fname_; int line_; int severity_; }; // LogMessageFatal ensures the process will exit in failure after // logging this message. class LogMessageFatal : public LogMessage { public: LogMessageFatal(const char* file, int line) TF_ATTRIBUTE_COLD; ~LogMessageFatal() TF_ATTRIBUTE_NORETURN; }; #define _TF_LOG_INFO \ ::tensorflow::internal::LogMessage(__FILE__, __LINE__, tensorflow::INFO) #define _TF_LOG_WARNING \ ::tensorflow::internal::LogMessage(__FILE__, __LINE__, tensorflow::WARNING) #define _TF_LOG_ERROR \ ::tensorflow::internal::LogMessage(__FILE__, __LINE__, tensorflow::ERROR) #define _TF_LOG_FATAL \ ::tensorflow::internal::LogMessageFatal(__FILE__, __LINE__) #define LOG(severity) _TF_LOG_##severity // TODO(jeff): Define a proper implementation of VLOG_IS_ON #define VLOG_IS_ON(lvl) ((lvl) <= 0) #define VLOG(lvl) \ if (VLOG_IS_ON(lvl)) \ ::tensorflow::internal::LogMessage(__FILE__, __LINE__, tensorflow::INFO) // CHECK dies with a fatal error if condition is not true. It is *not* // controlled by NDEBUG, so the check will be executed regardless of // compilation mode. Therefore, it is safe to do things like: // CHECK(fp->Write(x) == 4) #define CHECK(condition) \ if (TF_PREDICT_FALSE(!(condition))) \ LOG(FATAL) << "Check failed: " #condition " " // Function is overloaded for integral types to allow static const // integrals declared in classes and not defined to be used as arguments to // CHECK* macros. It's not encouraged though. template inline const T& GetReferenceableValue(const T& t) { return t; } inline char GetReferenceableValue(char t) { return t; } inline unsigned char GetReferenceableValue(unsigned char t) { return t; } inline signed char GetReferenceableValue(signed char t) { return t; } inline short GetReferenceableValue(short t) { return t; } inline unsigned short GetReferenceableValue(unsigned short t) { return t; } inline int GetReferenceableValue(int t) { return t; } inline unsigned int GetReferenceableValue(unsigned int t) { return t; } inline long GetReferenceableValue(long t) { return t; } inline unsigned long GetReferenceableValue(unsigned long t) { return t; } inline long long GetReferenceableValue(long long t) { return t; } inline unsigned long long GetReferenceableValue(unsigned long long t) { return t; } // This formats a value for a failing CHECK_XX statement. Ordinarily, // it uses the definition for operator<<, with a few special cases below. template inline void MakeCheckOpValueString(std::ostream* os, const T& v) { (*os) << v; } // Overrides for char types provide readable values for unprintable // characters. template <> void MakeCheckOpValueString(std::ostream* os, const char& v); template <> void MakeCheckOpValueString(std::ostream* os, const signed char& v); template <> void MakeCheckOpValueString(std::ostream* os, const unsigned char& v); #if LANG_CXX11 // We need an explicit specialization for std::nullptr_t. template <> void MakeCheckOpValueString(std::ostream* os, const std::nullptr_t& p); #endif // A container for a string pointer which can be evaluated to a bool - // true iff the pointer is non-NULL. struct CheckOpString { CheckOpString(string* str) : str_(str) {} // No destructor: if str_ is non-NULL, we're about to LOG(FATAL), // so there's no point in cleaning up str_. operator bool() const { return TF_PREDICT_FALSE(str_ != NULL); } string* str_; }; // Build the error message string. Specify no inlining for code size. template string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) TF_ATTRIBUTE_NOINLINE; // A helper class for formatting "expr (V1 vs. V2)" in a CHECK_XX // statement. See MakeCheckOpString for sample usage. Other // approaches were considered: use of a template method (e.g., // base::BuildCheckOpString(exprtext, base::Print, &v1, // base::Print, &v2), however this approach has complications // related to volatile arguments and function-pointer arguments). class CheckOpMessageBuilder { public: // Inserts "exprtext" and " (" to the stream. explicit CheckOpMessageBuilder(const char* exprtext); // Deletes "stream_". ~CheckOpMessageBuilder(); // For inserting the first variable. std::ostream* ForVar1() { return stream_; } // For inserting the second variable (adds an intermediate " vs. "). std::ostream* ForVar2(); // Get the result (inserts the closing ")"). string* NewString(); private: std::ostringstream* stream_; }; template string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) { CheckOpMessageBuilder comb(exprtext); MakeCheckOpValueString(comb.ForVar1(), v1); MakeCheckOpValueString(comb.ForVar2(), v2); return comb.NewString(); } // Helper functions for CHECK_OP macro. // The (int, int) specialization works around the issue that the compiler // will not instantiate the template version of the function on values of // unnamed enum type - see comment below. #define TF_DEFINE_CHECK_OP_IMPL(name, op) \ template \ inline string* name##Impl(const T1& v1, const T2& v2, \ const char* exprtext) { \ if (TF_PREDICT_TRUE(v1 op v2)) \ return NULL; \ else \ return ::tensorflow::internal::MakeCheckOpString(v1, v2, exprtext); \ } \ inline string* name##Impl(int v1, int v2, const char* exprtext) { \ return name##Impl(v1, v2, exprtext); \ } // We use the full name Check_EQ, Check_NE, etc. in case the file including // base/logging.h provides its own #defines for the simpler names EQ, NE, etc. // This happens if, for example, those are used as token names in a // yacc grammar. TF_DEFINE_CHECK_OP_IMPL(Check_EQ, == ) // Compilation error with CHECK_EQ(NULL, x)? TF_DEFINE_CHECK_OP_IMPL(Check_NE, != ) // Use CHECK(x == NULL) instead. TF_DEFINE_CHECK_OP_IMPL(Check_LE, <= ) TF_DEFINE_CHECK_OP_IMPL(Check_LT, < ) TF_DEFINE_CHECK_OP_IMPL(Check_GE, >= ) TF_DEFINE_CHECK_OP_IMPL(Check_GT, > ) #undef TF_DEFINE_CHECK_OP_IMPL // In optimized mode, use CheckOpString to hint to compiler that // the while condition is unlikely. #define CHECK_OP_LOG(name, op, val1, val2) \ while (::tensorflow::internal::CheckOpString _result = \ ::tensorflow::internal::name##Impl( \ ::tensorflow::internal::GetReferenceableValue(val1), \ ::tensorflow::internal::GetReferenceableValue(val2), \ #val1 " " #op " " #val2)) \ ::tensorflow::internal::LogMessageFatal(__FILE__, __LINE__) << *(_result.str_) #define CHECK_OP(name, op, val1, val2) CHECK_OP_LOG(name, op, val1, val2) // CHECK_EQ/NE/... #define CHECK_EQ(val1, val2) CHECK_OP(Check_EQ, ==, val1, val2) #define CHECK_NE(val1, val2) CHECK_OP(Check_NE, !=, val1, val2) #define CHECK_LE(val1, val2) CHECK_OP(Check_LE, <=, val1, val2) #define CHECK_LT(val1, val2) CHECK_OP(Check_LT, <, val1, val2) #define CHECK_GE(val1, val2) CHECK_OP(Check_GE, >=, val1, val2) #define CHECK_GT(val1, val2) CHECK_OP(Check_GT, >, val1, val2) #define CHECK_NOTNULL(val) \ ::tensorflow::internal::CheckNotNull(__FILE__, __LINE__, \ "'" #val "' Must be non NULL", (val)) #ifndef NDEBUG // DCHECK_EQ/NE/... #define DCHECK(condition) CHECK(condition) #define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2) #define DCHECK_NE(val1, val2) CHECK_NE(val1, val2) #define DCHECK_LE(val1, val2) CHECK_LE(val1, val2) #define DCHECK_LT(val1, val2) CHECK_LT(val1, val2) #define DCHECK_GE(val1, val2) CHECK_GE(val1, val2) #define DCHECK_GT(val1, val2) CHECK_GT(val1, val2) #else #define DCHECK(condition) \ while (false && (condition)) LOG(FATAL) // NDEBUG is defined, so DCHECK_EQ(x, y) and so on do nothing. // However, we still want the compiler to parse x and y, because // we don't want to lose potentially useful errors and warnings. // _DCHECK_NOP is a helper, and should not be used outside of this file. #define _TF_DCHECK_NOP(x, y) \ while (false && ((void)(x), (void)(y), 0)) LOG(FATAL) #define DCHECK_EQ(x, y) _TF_DCHECK_NOP(x, y) #define DCHECK_NE(x, y) _TF_DCHECK_NOP(x, y) #define DCHECK_LE(x, y) _TF_DCHECK_NOP(x, y) #define DCHECK_LT(x, y) _TF_DCHECK_NOP(x, y) #define DCHECK_GE(x, y) _TF_DCHECK_NOP(x, y) #define DCHECK_GT(x, y) _TF_DCHECK_NOP(x, y) #endif // These are for when you don't want a CHECK failure to print a verbose // stack trace. The implementation of CHECK* in this file already doesn't. #define QCHECK(condition) CHECK(condition) #define QCHECK_EQ(x, y) CHECK_EQ(x, y) #define QCHECK_NE(x, y) CHECK_NE(x, y) #define QCHECK_LE(x, y) CHECK_LE(x, y) #define QCHECK_LT(x, y) CHECK_LT(x, y) #define QCHECK_GE(x, y) CHECK_GE(x, y) #define QCHECK_GT(x, y) CHECK_GT(x, y) template T&& CheckNotNull(const char* file, int line, const char* exprtext, T&& t) { if (t == nullptr) { LogMessageFatal(file, line) << string(exprtext); } return std::forward(t); } } // namespace internal } // namespace tensorflow #endif // TENSORFLOW_PLATFORM_DEFAULT_LOGGING_H_