Home | History | Annotate | Download | only in core
      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_CORE_LIB_CORE_STATUS_H_
     17 #define TENSORFLOW_CORE_LIB_CORE_STATUS_H_
     18 
     19 #include <functional>
     20 #include <iosfwd>
     21 #include <memory>
     22 #include <string>
     23 #include "tensorflow/core/lib/core/error_codes.pb.h"
     24 #include "tensorflow/core/lib/core/stringpiece.h"
     25 #include "tensorflow/core/platform/logging.h"
     26 #include "tensorflow/core/platform/macros.h"
     27 #include "tensorflow/core/platform/types.h"
     28 
     29 namespace tensorflow {
     30 
     31 #if defined(__clang__)
     32 // Only clang supports warn_unused_result as a type annotation.
     33 class TF_MUST_USE_RESULT Status;
     34 #endif
     35 
     36 /// @ingroup core
     37 /// Denotes success or failure of a call in Tensorflow.
     38 class Status {
     39  public:
     40   /// Create a success status.
     41   Status() {}
     42 
     43   /// \brief Create a status with the specified error code and msg as a
     44   /// human-readable string containing more detailed information.
     45   Status(tensorflow::error::Code code, tensorflow::StringPiece msg);
     46 
     47   /// Copy the specified status.
     48   Status(const Status& s);
     49   void operator=(const Status& s);
     50 
     51   static Status OK() { return Status(); }
     52 
     53   /// Returns true iff the status indicates success.
     54   bool ok() const { return (state_ == NULL); }
     55 
     56   tensorflow::error::Code code() const {
     57     return ok() ? tensorflow::error::OK : state_->code;
     58   }
     59 
     60   const string& error_message() const {
     61     return ok() ? empty_string() : state_->msg;
     62   }
     63 
     64   bool operator==(const Status& x) const;
     65   bool operator!=(const Status& x) const;
     66 
     67   /// \brief If `ok()`, stores `new_status` into `*this`.  If `!ok()`,
     68   /// preserves the current status, but may augment with additional
     69   /// information about `new_status`.
     70   ///
     71   /// Convenient way of keeping track of the first error encountered.
     72   /// Instead of:
     73   ///   `if (overall_status.ok()) overall_status = new_status`
     74   /// Use:
     75   ///   `overall_status.Update(new_status);`
     76   void Update(const Status& new_status);
     77 
     78   /// \brief Return a string representation of this status suitable for
     79   /// printing. Returns the string `"OK"` for success.
     80   string ToString() const;
     81 
     82   // Ignores any errors. This method does nothing except potentially suppress
     83   // complaints from any tools that are checking that errors are not dropped on
     84   // the floor.
     85   void IgnoreError() const;
     86 
     87  private:
     88   static const string& empty_string();
     89   struct State {
     90     tensorflow::error::Code code;
     91     string msg;
     92   };
     93   // OK status has a `NULL` state_.  Otherwise, `state_` points to
     94   // a `State` structure containing the error code and message(s)
     95   std::unique_ptr<State> state_;
     96 
     97   void SlowCopyFrom(const State* src);
     98 };
     99 
    100 // Helper class to manage multiple child status values.
    101 class StatusGroup {
    102  public:
    103   // Return a merged status with combined child status messages.
    104   //
    105   // The status code returned is OK if all children were successful, otherwise
    106   // the first non-OK child status code is reported.
    107   Status as_status() const;
    108 
    109   bool ok() const { return ok_; }
    110 
    111   // Augment this group with the child status `status`.
    112   void Update(const Status& status);
    113 
    114  private:
    115   bool ok_ = true;
    116   size_t num_ok_ = 0;
    117   std::vector<Status> children_;
    118 };
    119 
    120 inline Status::Status(const Status& s)
    121     : state_((s.state_ == NULL) ? NULL : new State(*s.state_)) {}
    122 
    123 inline void Status::operator=(const Status& s) {
    124   // The following condition catches both aliasing (when this == &s),
    125   // and the common case where both s and *this are ok.
    126   if (state_ != s.state_) {
    127     SlowCopyFrom(s.state_.get());
    128   }
    129 }
    130 
    131 inline bool Status::operator==(const Status& x) const {
    132   return (this->state_ == x.state_) || (ToString() == x.ToString());
    133 }
    134 
    135 inline bool Status::operator!=(const Status& x) const { return !(*this == x); }
    136 
    137 /// @ingroup core
    138 std::ostream& operator<<(std::ostream& os, const Status& x);
    139 
    140 typedef std::function<void(const Status&)> StatusCallback;
    141 
    142 extern tensorflow::string* TfCheckOpHelperOutOfLine(
    143     const ::tensorflow::Status& v, const char* msg);
    144 
    145 inline tensorflow::string* TfCheckOpHelper(::tensorflow::Status v,
    146                                            const char* msg) {
    147   if (v.ok()) return nullptr;
    148   return TfCheckOpHelperOutOfLine(v, msg);
    149 }
    150 
    151 #define TF_DO_CHECK_OK(val, level)                                \
    152   while (auto _result = ::tensorflow::TfCheckOpHelper(val, #val)) \
    153   LOG(level) << *(_result)
    154 
    155 #define TF_CHECK_OK(val) TF_DO_CHECK_OK(val, FATAL)
    156 #define TF_QCHECK_OK(val) TF_DO_CHECK_OK(val, QFATAL)
    157 
    158 // DEBUG only version of TF_CHECK_OK.  Compiler still parses 'val' even in opt
    159 // mode.
    160 #ifndef NDEBUG
    161 #define TF_DCHECK_OK(val) TF_CHECK_OK(val)
    162 #else
    163 #define TF_DCHECK_OK(val) \
    164   while (false && (::tensorflow::Status::OK() == (val))) LOG(FATAL)
    165 #endif
    166 
    167 }  // namespace tensorflow
    168 
    169 #endif  // TENSORFLOW_CORE_LIB_CORE_STATUS_H_
    170