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