Home | History | Annotate | Download | only in default
      1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
      2 
      3 Licensed under the Apache License, Version 2.0 (the "License");
      4 you may not use this file except in compliance with the License.
      5 You may obtain a copy of the License at
      6 
      7     http://www.apache.org/licenses/LICENSE-2.0
      8 
      9 Unless required by applicable law or agreed to in writing, software
     10 distributed under the License is distributed on an "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 See the License for the specific language governing permissions and
     13 limitations under the License.
     14 ==============================================================================*/
     15 
     16 #ifndef TENSORFLOW_PLATFORM_DEFAULT_LOGGING_H_
     17 #define TENSORFLOW_PLATFORM_DEFAULT_LOGGING_H_
     18 
     19 // IWYU pragma: private, include "third_party/tensorflow/core/platform/logging.h"
     20 // IWYU pragma: friend third_party/tensorflow/core/platform/logging.h
     21 
     22 #include <limits>
     23 #include <sstream>
     24 #include "tensorflow/core/platform/macros.h"
     25 #include "tensorflow/core/platform/types.h"
     26 
     27 // TODO(mrry): Prevent this Windows.h #define from leaking out of our headers.
     28 #undef ERROR
     29 
     30 namespace tensorflow {
     31 const int INFO = 0;            // base_logging::INFO;
     32 const int WARNING = 1;         // base_logging::WARNING;
     33 const int ERROR = 2;           // base_logging::ERROR;
     34 const int FATAL = 3;           // base_logging::FATAL;
     35 const int NUM_SEVERITIES = 4;  // base_logging::NUM_SEVERITIES;
     36 
     37 namespace internal {
     38 
     39 class LogMessage : public std::basic_ostringstream<char> {
     40  public:
     41   LogMessage(const char* fname, int line, int severity);
     42   ~LogMessage();
     43 
     44   // Returns the minimum log level for VLOG statements.
     45   // E.g., if MinVLogLevel() is 2, then VLOG(2) statements will produce output,
     46   // but VLOG(3) will not. Defaults to 0.
     47   static int64 MinVLogLevel();
     48 
     49  protected:
     50   void GenerateLogMessage();
     51 
     52  private:
     53   const char* fname_;
     54   int line_;
     55   int severity_;
     56 };
     57 
     58 // LogMessageFatal ensures the process will exit in failure after
     59 // logging this message.
     60 class LogMessageFatal : public LogMessage {
     61  public:
     62   LogMessageFatal(const char* file, int line) TF_ATTRIBUTE_COLD;
     63   TF_ATTRIBUTE_NORETURN ~LogMessageFatal();
     64 };
     65 
     66 #define _TF_LOG_INFO \
     67   ::tensorflow::internal::LogMessage(__FILE__, __LINE__, tensorflow::INFO)
     68 #define _TF_LOG_WARNING \
     69   ::tensorflow::internal::LogMessage(__FILE__, __LINE__, tensorflow::WARNING)
     70 #define _TF_LOG_ERROR \
     71   ::tensorflow::internal::LogMessage(__FILE__, __LINE__, tensorflow::ERROR)
     72 #define _TF_LOG_FATAL \
     73   ::tensorflow::internal::LogMessageFatal(__FILE__, __LINE__)
     74 
     75 #define _TF_LOG_QFATAL _TF_LOG_FATAL
     76 
     77 #define LOG(severity) _TF_LOG_##severity
     78 
     79 #ifdef IS_MOBILE_PLATFORM
     80 // Turn VLOG off when under mobile devices for considerations of binary size.
     81 #define VLOG_IS_ON(lvl) ((lvl) <= 0)
     82 #else
     83 // Otherwise, Set TF_CPP_MIN_VLOG_LEVEL environment to update minimum log level
     84 // of VLOG
     85 #define VLOG_IS_ON(lvl) \
     86   ((lvl) <= ::tensorflow::internal::LogMessage::MinVLogLevel())
     87 #endif
     88 
     89 #define VLOG(lvl)                        \
     90   if (TF_PREDICT_FALSE(VLOG_IS_ON(lvl))) \
     91   ::tensorflow::internal::LogMessage(__FILE__, __LINE__, tensorflow::INFO)
     92 
     93 // CHECK dies with a fatal error if condition is not true.  It is *not*
     94 // controlled by NDEBUG, so the check will be executed regardless of
     95 // compilation mode.  Therefore, it is safe to do things like:
     96 //    CHECK(fp->Write(x) == 4)
     97 #define CHECK(condition)              \
     98   if (TF_PREDICT_FALSE(!(condition))) \
     99   LOG(FATAL) << "Check failed: " #condition " "
    100 
    101 // Function is overloaded for integral types to allow static const
    102 // integrals declared in classes and not defined to be used as arguments to
    103 // CHECK* macros. It's not encouraged though.
    104 template <typename T>
    105 inline const T& GetReferenceableValue(const T& t) {
    106   return t;
    107 }
    108 inline char GetReferenceableValue(char t) { return t; }
    109 inline unsigned char GetReferenceableValue(unsigned char t) { return t; }
    110 inline signed char GetReferenceableValue(signed char t) { return t; }
    111 inline short GetReferenceableValue(short t) { return t; }
    112 inline unsigned short GetReferenceableValue(unsigned short t) { return t; }
    113 inline int GetReferenceableValue(int t) { return t; }
    114 inline unsigned int GetReferenceableValue(unsigned int t) { return t; }
    115 inline long GetReferenceableValue(long t) { return t; }
    116 inline unsigned long GetReferenceableValue(unsigned long t) { return t; }
    117 inline long long GetReferenceableValue(long long t) { return t; }
    118 inline unsigned long long GetReferenceableValue(unsigned long long t) {
    119   return t;
    120 }
    121 
    122 // This formats a value for a failing CHECK_XX statement.  Ordinarily,
    123 // it uses the definition for operator<<, with a few special cases below.
    124 template <typename T>
    125 inline void MakeCheckOpValueString(std::ostream* os, const T& v) {
    126   (*os) << v;
    127 }
    128 
    129 // Overrides for char types provide readable values for unprintable
    130 // characters.
    131 template <>
    132 void MakeCheckOpValueString(std::ostream* os, const char& v);
    133 template <>
    134 void MakeCheckOpValueString(std::ostream* os, const signed char& v);
    135 template <>
    136 void MakeCheckOpValueString(std::ostream* os, const unsigned char& v);
    137 
    138 #if LANG_CXX11
    139 // We need an explicit specialization for std::nullptr_t.
    140 template <>
    141 void MakeCheckOpValueString(std::ostream* os, const std::nullptr_t& p);
    142 #endif
    143 
    144 // A container for a string pointer which can be evaluated to a bool -
    145 // true iff the pointer is non-NULL.
    146 struct CheckOpString {
    147   CheckOpString(string* str) : str_(str) {}
    148   // No destructor: if str_ is non-NULL, we're about to LOG(FATAL),
    149   // so there's no point in cleaning up str_.
    150   operator bool() const { return TF_PREDICT_FALSE(str_ != NULL); }
    151   string* str_;
    152 };
    153 
    154 // Build the error message string. Specify no inlining for code size.
    155 template <typename T1, typename T2>
    156 string* MakeCheckOpString(const T1& v1, const T2& v2,
    157                           const char* exprtext) TF_ATTRIBUTE_NOINLINE;
    158 
    159 // A helper class for formatting "expr (V1 vs. V2)" in a CHECK_XX
    160 // statement.  See MakeCheckOpString for sample usage.  Other
    161 // approaches were considered: use of a template method (e.g.,
    162 // base::BuildCheckOpString(exprtext, base::Print<T1>, &v1,
    163 // base::Print<T2>, &v2), however this approach has complications
    164 // related to volatile arguments and function-pointer arguments).
    165 class CheckOpMessageBuilder {
    166  public:
    167   // Inserts "exprtext" and " (" to the stream.
    168   explicit CheckOpMessageBuilder(const char* exprtext);
    169   // Deletes "stream_".
    170   ~CheckOpMessageBuilder();
    171   // For inserting the first variable.
    172   std::ostream* ForVar1() { return stream_; }
    173   // For inserting the second variable (adds an intermediate " vs. ").
    174   std::ostream* ForVar2();
    175   // Get the result (inserts the closing ")").
    176   string* NewString();
    177 
    178  private:
    179   std::ostringstream* stream_;
    180 };
    181 
    182 template <typename T1, typename T2>
    183 string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) {
    184   CheckOpMessageBuilder comb(exprtext);
    185   MakeCheckOpValueString(comb.ForVar1(), v1);
    186   MakeCheckOpValueString(comb.ForVar2(), v2);
    187   return comb.NewString();
    188 }
    189 
    190 // Helper functions for CHECK_OP macro.
    191 // The (int, int) specialization works around the issue that the compiler
    192 // will not instantiate the template version of the function on values of
    193 // unnamed enum type - see comment below.
    194 // The (size_t, int) and (int, size_t) specialization are to handle unsigned
    195 // comparison errors while still being thorough with the comparison.
    196 #define TF_DEFINE_CHECK_OP_IMPL(name, op)                                 \
    197   template <typename T1, typename T2>                                     \
    198   inline string* name##Impl(const T1& v1, const T2& v2,                   \
    199                             const char* exprtext) {                       \
    200     if (TF_PREDICT_TRUE(v1 op v2))                                        \
    201       return NULL;                                                        \
    202     else                                                                  \
    203       return ::tensorflow::internal::MakeCheckOpString(v1, v2, exprtext); \
    204   }                                                                       \
    205   inline string* name##Impl(int v1, int v2, const char* exprtext) {       \
    206     return name##Impl<int, int>(v1, v2, exprtext);                        \
    207   }                                                                       \
    208   inline string* name##Impl(const size_t v1, const int v2,                \
    209                             const char* exprtext) {                       \
    210     if (TF_PREDICT_FALSE(v2 < 0)) {                                       \
    211       return ::tensorflow::internal::MakeCheckOpString(v1, v2, exprtext); \
    212     }                                                                     \
    213     const size_t uval = (size_t)((unsigned)v1);                           \
    214     return name##Impl<size_t, size_t>(uval, v2, exprtext);                \
    215   }                                                                       \
    216   inline string* name##Impl(const int v1, const size_t v2,                \
    217                             const char* exprtext) {                       \
    218     if (TF_PREDICT_FALSE(v2 >= std::numeric_limits<int>::max())) {        \
    219       return ::tensorflow::internal::MakeCheckOpString(v1, v2, exprtext); \
    220     }                                                                     \
    221     const size_t uval = (size_t)((unsigned)v2);                           \
    222     return name##Impl<size_t, size_t>(v1, uval, exprtext);                \
    223   }
    224 
    225 // We use the full name Check_EQ, Check_NE, etc. in case the file including
    226 // base/logging.h provides its own #defines for the simpler names EQ, NE, etc.
    227 // This happens if, for example, those are used as token names in a
    228 // yacc grammar.
    229 TF_DEFINE_CHECK_OP_IMPL(Check_EQ,
    230                         ==)  // Compilation error with CHECK_EQ(NULL, x)?
    231 TF_DEFINE_CHECK_OP_IMPL(Check_NE, !=)  // Use CHECK(x == NULL) instead.
    232 TF_DEFINE_CHECK_OP_IMPL(Check_LE, <=)
    233 TF_DEFINE_CHECK_OP_IMPL(Check_LT, <)
    234 TF_DEFINE_CHECK_OP_IMPL(Check_GE, >=)
    235 TF_DEFINE_CHECK_OP_IMPL(Check_GT, >)
    236 #undef TF_DEFINE_CHECK_OP_IMPL
    237 
    238 // In optimized mode, use CheckOpString to hint to compiler that
    239 // the while condition is unlikely.
    240 #define CHECK_OP_LOG(name, op, val1, val2)                            \
    241   while (::tensorflow::internal::CheckOpString _result =              \
    242              ::tensorflow::internal::name##Impl(                      \
    243                  ::tensorflow::internal::GetReferenceableValue(val1), \
    244                  ::tensorflow::internal::GetReferenceableValue(val2), \
    245                  #val1 " " #op " " #val2))                            \
    246   ::tensorflow::internal::LogMessageFatal(__FILE__, __LINE__) << *(_result.str_)
    247 
    248 #define CHECK_OP(name, op, val1, val2) CHECK_OP_LOG(name, op, val1, val2)
    249 
    250 // CHECK_EQ/NE/...
    251 #define CHECK_EQ(val1, val2) CHECK_OP(Check_EQ, ==, val1, val2)
    252 #define CHECK_NE(val1, val2) CHECK_OP(Check_NE, !=, val1, val2)
    253 #define CHECK_LE(val1, val2) CHECK_OP(Check_LE, <=, val1, val2)
    254 #define CHECK_LT(val1, val2) CHECK_OP(Check_LT, <, val1, val2)
    255 #define CHECK_GE(val1, val2) CHECK_OP(Check_GE, >=, val1, val2)
    256 #define CHECK_GT(val1, val2) CHECK_OP(Check_GT, >, val1, val2)
    257 #define CHECK_NOTNULL(val)                                 \
    258   ::tensorflow::internal::CheckNotNull(__FILE__, __LINE__, \
    259                                        "'" #val "' Must be non NULL", (val))
    260 
    261 #ifndef NDEBUG
    262 // DCHECK_EQ/NE/...
    263 #define DCHECK(condition) CHECK(condition)
    264 #define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2)
    265 #define DCHECK_NE(val1, val2) CHECK_NE(val1, val2)
    266 #define DCHECK_LE(val1, val2) CHECK_LE(val1, val2)
    267 #define DCHECK_LT(val1, val2) CHECK_LT(val1, val2)
    268 #define DCHECK_GE(val1, val2) CHECK_GE(val1, val2)
    269 #define DCHECK_GT(val1, val2) CHECK_GT(val1, val2)
    270 
    271 #else
    272 
    273 #define DCHECK(condition) \
    274   while (false && (condition)) LOG(FATAL)
    275 
    276 // NDEBUG is defined, so DCHECK_EQ(x, y) and so on do nothing.
    277 // However, we still want the compiler to parse x and y, because
    278 // we don't want to lose potentially useful errors and warnings.
    279 // _DCHECK_NOP is a helper, and should not be used outside of this file.
    280 #define _TF_DCHECK_NOP(x, y) \
    281   while (false && ((void)(x), (void)(y), 0)) LOG(FATAL)
    282 
    283 #define DCHECK_EQ(x, y) _TF_DCHECK_NOP(x, y)
    284 #define DCHECK_NE(x, y) _TF_DCHECK_NOP(x, y)
    285 #define DCHECK_LE(x, y) _TF_DCHECK_NOP(x, y)
    286 #define DCHECK_LT(x, y) _TF_DCHECK_NOP(x, y)
    287 #define DCHECK_GE(x, y) _TF_DCHECK_NOP(x, y)
    288 #define DCHECK_GT(x, y) _TF_DCHECK_NOP(x, y)
    289 
    290 #endif
    291 
    292 // These are for when you don't want a CHECK failure to print a verbose
    293 // stack trace.  The implementation of CHECK* in this file already doesn't.
    294 #define QCHECK(condition) CHECK(condition)
    295 #define QCHECK_EQ(x, y) CHECK_EQ(x, y)
    296 #define QCHECK_NE(x, y) CHECK_NE(x, y)
    297 #define QCHECK_LE(x, y) CHECK_LE(x, y)
    298 #define QCHECK_LT(x, y) CHECK_LT(x, y)
    299 #define QCHECK_GE(x, y) CHECK_GE(x, y)
    300 #define QCHECK_GT(x, y) CHECK_GT(x, y)
    301 
    302 template <typename T>
    303 T&& CheckNotNull(const char* file, int line, const char* exprtext, T&& t) {
    304   if (t == nullptr) {
    305     LogMessageFatal(file, line) << string(exprtext);
    306   }
    307   return std::forward<T>(t);
    308 }
    309 
    310 int64 MinLogLevelFromEnv();
    311 
    312 int64 MinVLogLevelFromEnv();
    313 
    314 }  // namespace internal
    315 }  // namespace tensorflow
    316 
    317 #endif  // TENSORFLOW_PLATFORM_DEFAULT_LOGGING_H_
    318