00001 // Copyright (c) 2017, The Regents of the University of California 00002 // All rights reserved. 00003 // 00004 // Redistribution and use in source and binary forms, with or without 00005 // modification, are permitted provided that the following conditions are met: 00006 // * Redistributions of source code must retain the above copyright 00007 // notice, this list of conditions and the following disclaimer. 00008 // * Redistributions in binary form must reproduce the above copyright 00009 // notice, this list of conditions and the following disclaimer in the 00010 // documentation and/or other materials provided with the distribution. 00011 // * Neither the name of the University of California nor the 00012 // names of its contributors may be used to endorse or promote products 00013 // derived from this software without specific prior written permission. 00014 // 00015 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00016 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00017 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00018 // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA 00019 // BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00020 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00021 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00022 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00023 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00024 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00025 // POSSIBILITY OF SUCH DAMAGE. 00026 00027 // StatusOr<T> is the union of a Status object and a T 00028 // object. StatusOr models the concept of an object that is either a 00029 // usable value, or an error Status explaining why such a value is 00030 // not present. To this end, StatusOr<T> does not allow its Status 00031 // value to be Status::OK. Further, StatusOr<T*> does not allow the 00032 // contained pointer to be NULL. 00033 // 00034 // The primary use-case for StatusOr<T> is as the return value of a 00035 // function which may fail. 00036 // 00037 // Example client usage for a StatusOr<T>, where T is not a pointer: 00038 // 00039 // StatusOr<float> result = DoBigCalculationThatCouldFail(); 00040 // if (result.ok()) { 00041 // float answer = result.ValueOrDie(); 00042 // printf("Big calculation yielded: %f", answer); 00043 // } else { 00044 // LOG(ERROR) << result.status(); 00045 // } 00046 // 00047 // Example client usage for a StatusOr<T*>: 00048 // 00049 // StatusOr<Foo*> result = FooFactory::MakeNewFoo(arg); 00050 // if (result.ok()) { 00051 // std::unique_ptr<Foo> foo(result.ValueOrDie()); 00052 // foo->DoSomethingCool(); 00053 // } else { 00054 // LOG(ERROR) << result.status(); 00055 // } 00056 // 00057 // Example client usage for a StatusOr<std::unique_ptr<T>>: 00058 // 00059 // StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg); 00060 // if (result.ok()) { 00061 // std::unique_ptr<Foo> foo = result.ConsumeValueOrDie(); 00062 // foo->DoSomethingCool(); 00063 // } else { 00064 // LOG(ERROR) << result.status(); 00065 // } 00066 // 00067 // Example factory implementation returning StatusOr<T*>: 00068 // 00069 // StatusOr<Foo*> FooFactory::MakeNewFoo(int arg) { 00070 // if (arg <= 0) { 00071 // return ::util::Status(::util::error::INVALID_ARGUMENT, 00072 // "Arg must be positive"); 00073 // } else { 00074 // return new Foo(arg); 00075 // } 00076 // } 00077 // 00078 00079 #ifndef UTIL_STATUSOR_H_ 00080 #define UTIL_STATUSOR_H_ 00081 00082 #include <assert.h> 00083 00084 #include <new> 00085 #include <string> 00086 #include <utility> 00087 00088 #include "util/status.h" 00089 00090 namespace util { 00091 00092 template<typename T> 00093 class StatusOr { 00094 template<typename U> friend class StatusOr; 00095 00096 public: 00097 // Construct a new StatusOr with Status::UNKNOWN status 00098 StatusOr(); 00099 00100 // Construct a new StatusOr with the given non-ok status. After calling 00101 // this constructor, calls to ValueOrDie() will CHECK-fail. 00102 // 00103 // NOTE: Not explicit - we want to use StatusOr<T> as a return 00104 // value, so it is convenient and sensible to be able to do 'return 00105 // Status()' when the return type is StatusOr<T>. 00106 // 00107 // REQUIRES: status != Status::OK. This requirement is DCHECKed. 00108 // In optimized builds, passing Status::OK here will have the effect 00109 // of passing PosixErrorSpace::EINVAL as a fallback. 00110 StatusOr(const Status& status); // NOLINT 00111 00112 // Construct a new StatusOr with the given value. If T is a plain pointer, 00113 // value must not be NULL. After calling this constructor, calls to 00114 // ValueOrDie() will succeed, and calls to status() will return OK. 00115 // 00116 // NOTE: Not explicit - we want to use StatusOr<T> as a return type 00117 // so it is convenient and sensible to be able to do 'return T()' 00118 // when when the return type is StatusOr<T>. 00119 // 00120 // REQUIRES: if T is a plain pointer, value != NULL. This requirement is 00121 // DCHECKed. In optimized builds, passing a NULL pointer here will have 00122 // the effect of passing PosixErrorSpace::EINVAL as a fallback. 00123 StatusOr(const T& value); // NOLINT 00124 00125 // Copy constructor. 00126 StatusOr(const StatusOr& other); 00127 00128 // Conversion copy constructor, T must be copy constructible from U 00129 template<typename U> 00130 StatusOr(const StatusOr<U>& other); 00131 00132 // Assignment operator. 00133 StatusOr& operator=(const StatusOr& other); 00134 00135 // Conversion assignment operator, T must be assignable from U 00136 template<typename U> 00137 StatusOr& operator=(const StatusOr<U>& other); 00138 00139 // Rvalue-reference overloads of the other constructors and assignment 00140 // operators, to support move-only types and avoid unnecessary copying. 00141 StatusOr(T&& value); // NOLINT 00142 00143 // Move conversion operator to avoid unecessary copy. 00144 // T must be assignable from U. 00145 // Not marked with explicit so the implicit conversion can happen. 00146 template <typename U> 00147 StatusOr(StatusOr<U>&& other); // NOLINT 00148 00149 // Move assignment opeartor to avoid unnecessary copy. 00150 // T must be assignable from U 00151 template <typename U> 00152 StatusOr& operator=(StatusOr<U>&& other); 00153 00154 // Returns a reference to our status. If this contains a T, then 00155 // returns Status::OK. 00156 const Status& status() const; 00157 00158 // Returns this->status().ok() 00159 bool ok() const; 00160 00161 // Returns a reference to our current value, or CHECK-fails if !this->ok(). 00162 // If you need to initialize a T object from the stored value, 00163 // ConsumeValueOrDie() may be more efficient. 00164 const T& ValueOrDie() const; 00165 00166 // Returns our current value, requires this->ok(). Use this if 00167 // you would otherwise want to say std::move(s.ValueOrDie()), for example 00168 // if you need to initialize a T object from the stored value and you don't 00169 // need subsequent access to the stored value. It uses T's move constructor, 00170 // if it has one, so it will work with move-only types, and will often be 00171 // more efficient than ValueOrDie, but may leave the stored value 00172 // in an arbitrary valid state. 00173 T ConsumeValueOrDie(); 00174 00175 private: 00176 void CheckValueNotNull(const T& value); 00177 00178 template <typename U> 00179 struct IsNull { 00180 // For non-pointer U, a reference can never be NULL. 00181 static inline bool IsValueNull(const U& t) { return false; } 00182 }; 00183 00184 template <typename U> 00185 struct IsNull<U*> { 00186 static inline bool IsValueNull(const U* t) { return t == NULL; } 00187 }; 00188 00189 Status status_; 00190 T value_; 00191 }; 00192 00194 // Implementation details for StatusOr<T> 00195 00196 namespace internal { 00197 00198 class StatusOrHelper { 00199 public: 00200 // Move type-agnostic error handling to the .cc. 00201 static void Crash(const util::Status& status); 00202 00203 // Customized behavior for StatusOr<T> vs. StatusOr<T*> 00204 template<typename T> 00205 struct Specialize; 00206 }; 00207 00208 template<typename T> 00209 struct StatusOrHelper::Specialize { 00210 // For non-pointer T, a reference can never be NULL. 00211 static inline bool IsValueNull(const T& t) { return false; } 00212 }; 00213 00214 template<typename T> 00215 struct StatusOrHelper::Specialize<T*> { 00216 static inline bool IsValueNull(const T* t) { return t == NULL; } 00217 }; 00218 00219 } // namespace internal 00220 00221 template<typename T> 00222 inline StatusOr<T>::StatusOr() 00223 : status_(util::Status::UNKNOWN) { 00224 } 00225 00226 template<typename T> 00227 inline StatusOr<T>::StatusOr(const Status& status) { 00228 if (status.ok()) { 00229 status_ = Status(error::INTERNAL, "Status::OK is not a valid argument."); 00230 } else { 00231 status_ = status; 00232 } 00233 } 00234 00235 template<typename T> 00236 inline StatusOr<T>::StatusOr(const T& value) { 00237 if (internal::StatusOrHelper::Specialize<T>::IsValueNull(value)) { 00238 status_ = Status(error::INTERNAL, "NULL is not a vaild argument."); 00239 } else { 00240 status_ = Status::OK; 00241 value_ = value; 00242 } 00243 } 00244 00245 template<typename T> 00246 inline StatusOr<T>::StatusOr(const StatusOr<T>& other) 00247 : status_(other.status_), value_(other.value_) { 00248 } 00249 00250 template<typename T> 00251 inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<T>& other) { 00252 status_ = other.status_; 00253 value_ = other.value_; 00254 return *this; 00255 } 00256 00257 template<typename T> 00258 template<typename U> 00259 inline StatusOr<T>::StatusOr(const StatusOr<U>& other) 00260 : status_(other.status_), value_(other.status_.ok() ? other.value_ : T()) { 00261 } 00262 00263 template<typename T> 00264 template<typename U> 00265 inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<U>& other) { 00266 status_ = other.status_; 00267 if (status_.ok()) value_ = other.value_; 00268 return *this; 00269 } 00270 00271 template<typename T> 00272 inline const Status& StatusOr<T>::status() const { 00273 return status_; 00274 } 00275 00276 template<typename T> 00277 inline bool StatusOr<T>::ok() const { 00278 return status().ok(); 00279 } 00280 00281 template<typename T> 00282 inline const T& StatusOr<T>::ValueOrDie() const { 00283 if (!status_.ok()) { 00284 internal::StatusOrHelper::Crash(status_); 00285 } 00286 return value_; 00287 } 00288 00289 // Adpoted from tensorflow/stream_executor/lib/statusor.h 00290 00291 template <typename T> 00292 inline StatusOr<T>::StatusOr(T&& value) 00293 : status_() { 00294 CheckValueNotNull(value); 00295 value_ = std::move(value); 00296 } 00297 00298 template <typename T> 00299 inline T StatusOr<T>::ConsumeValueOrDie() { 00300 if (!status_.ok()) { 00301 internal::StatusOrHelper::Crash(status_); 00302 } 00303 return std::move(value_); 00304 } 00305 00306 template <typename T> 00307 template <typename U> 00308 inline StatusOr<T>::StatusOr(StatusOr<U>&& other) // NOLINT 00309 : status_(std::move(other.status_)), 00310 value_(std::move(other.value_)) {} 00311 00312 // Move assignment opeartor to avoid unnecessary copy. 00313 // T must be assignable from U 00314 template <typename T> 00315 template <typename U> 00316 inline StatusOr<T>& StatusOr<T>::operator=(StatusOr<U>&& other) { 00317 status_ = std::move(other.status_); 00318 value_ = std::move(other.value_); 00319 return *this; 00320 } 00321 00322 template <typename T> 00323 inline void StatusOr<T>::CheckValueNotNull(const T& value) { 00324 assert(!IsNull<T>::IsValueNull(value)); 00325 if (IsNull<T>::IsValueNull(value)) { 00326 status_ = 00327 Status(error::INTERNAL, 00328 "NULL is not a valid constructor argument to StatusOr<T*>"); 00329 } 00330 } 00331 00332 } // namespace util 00333 00334 #endif // UTIL_STATUSOR_H_ 00335 00336 00337 // Protocol Buffers - Google's data interchange format 00338 // Copyright 2008 Google Inc. All rights reserved. 00339 // https://developers.google.com/protocol-buffers/ 00340 // 00341 // Redistribution and use in source and binary forms, with or without 00342 // modification, are permitted provided that the following conditions are 00343 // met: 00344 // 00345 // * Redistributions of source code must retain the above copyright 00346 // notice, this list of conditions and the following disclaimer. 00347 // * Redistributions in binary form must reproduce the above 00348 // copyright notice, this list of conditions and the following disclaimer 00349 // in the documentation and/or other materials provided with the 00350 // distribution. 00351 // * Neither the name of Google Inc. nor the names of its 00352 // contributors may be used to endorse or promote products derived from 00353 // this software without specific prior written permission. 00354 // 00355 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00356 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00357 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00358 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00359 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00360 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00361 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00362 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00363 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00364 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00365 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00366 00367 00368 // Adpoted from tensorflow/stream_executor/lib/statusor.h 00369 // Copyright 2015 Google Inc. All Rights Reserved. 00370 // Licensed under the Apache License, Version 2.0 (the "License"); 00371 // you may not use this file except in compliance with the License. 00372 // You may obtain a copy of the License at 00373 // http://www.apache.org/licenses/LICENSE-2.0 00374 // Unless required by applicable law or agreed to in writing, software 00375 // distributed under the License is distributed on an "AS IS" BASIS, 00376 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00377 // See the License for the specific language governing permissions and 00378 // limitations under the License.