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