feat(3p/absl): import StatusOr from tensorflow
Additionally, add tests for the macros. A future CL will enable the tests in CI. Change-Id: Id4445a1aa65bf6751b87606f37654f3fc6d20efc Tested-By: kanepyork <rikingcoding@gmail.com> Reviewed-on: https://cl.tvl.fyi/c/depot/+/1274 Reviewed-by: tazjin <mail@tazj.in> Reviewed-by: glittershark <grfn@gws.fyi> Tested-by: BuildkiteCI
This commit is contained in:
parent
bd02cae032
commit
9f5f71616a
6 changed files with 1481 additions and 1 deletions
250
third_party/abseil_cpp/absl/status/statusor_internals.h
vendored
Normal file
250
third_party/abseil_cpp/absl/status/statusor_internals.h
vendored
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef ABSL_STATUS_STATUSOR_INTERNALS_H_
|
||||
#define ABSL_STATUS_STATUSOR_INTERNALS_H_
|
||||
|
||||
#include "absl/status/status.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
||||
namespace internal_statusor {
|
||||
|
||||
class Helper {
|
||||
public:
|
||||
// Move type-agnostic error handling to the .cc.
|
||||
static void HandleInvalidStatusCtorArg(Status*);
|
||||
ABSL_ATTRIBUTE_NORETURN static void Crash(const Status& status);
|
||||
};
|
||||
|
||||
// Construct an instance of T in `p` through placement new, passing Args... to
|
||||
// the constructor.
|
||||
// This abstraction is here mostly for the gcc performance fix.
|
||||
template <typename T, typename... Args>
|
||||
void PlacementNew(void* p, Args&&... args) {
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
// Teach gcc that 'p' cannot be null, fixing code size issues.
|
||||
if (p == nullptr) __builtin_unreachable();
|
||||
#endif
|
||||
new (p) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Helper base class to hold the data and all operations.
|
||||
// We move all this to a base class to allow mixing with the appropriate
|
||||
// TraitsBase specialization.
|
||||
template <typename T>
|
||||
class StatusOrData {
|
||||
template <typename U>
|
||||
friend class StatusOrData;
|
||||
|
||||
public:
|
||||
StatusOrData() = delete;
|
||||
|
||||
StatusOrData(const StatusOrData& other) {
|
||||
if (other.ok()) {
|
||||
MakeValue(other.data_);
|
||||
MakeStatus();
|
||||
} else {
|
||||
MakeStatus(other.status_);
|
||||
}
|
||||
}
|
||||
|
||||
StatusOrData(StatusOrData&& other) noexcept {
|
||||
if (other.ok()) {
|
||||
MakeValue(std::move(other.data_));
|
||||
MakeStatus();
|
||||
} else {
|
||||
MakeStatus(other.status_);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
StatusOrData(const StatusOrData<U>& other) {
|
||||
if (other.ok()) {
|
||||
MakeValue(other.data_);
|
||||
MakeStatus();
|
||||
} else {
|
||||
MakeStatus(other.status_);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
StatusOrData(StatusOrData<U>&& other) {
|
||||
if (other.ok()) {
|
||||
MakeValue(std::move(other.data_));
|
||||
MakeStatus();
|
||||
} else {
|
||||
MakeStatus(other.status_);
|
||||
}
|
||||
}
|
||||
|
||||
explicit StatusOrData(const T& value) : data_(value) { MakeStatus(); }
|
||||
explicit StatusOrData(T&& value) : data_(std::move(value)) { MakeStatus(); }
|
||||
|
||||
explicit StatusOrData(const Status& status) : status_(status) {
|
||||
EnsureNotOk();
|
||||
}
|
||||
explicit StatusOrData(Status&& status) : status_(std::move(status)) {
|
||||
EnsureNotOk();
|
||||
}
|
||||
|
||||
StatusOrData& operator=(const StatusOrData& other) {
|
||||
if (this == &other) return *this;
|
||||
if (other.ok())
|
||||
Assign(other.data_);
|
||||
else
|
||||
Assign(other.status_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
StatusOrData& operator=(StatusOrData&& other) {
|
||||
if (this == &other) return *this;
|
||||
if (other.ok())
|
||||
Assign(std::move(other.data_));
|
||||
else
|
||||
Assign(std::move(other.status_));
|
||||
return *this;
|
||||
}
|
||||
|
||||
~StatusOrData() {
|
||||
if (ok()) {
|
||||
status_.~Status();
|
||||
data_.~T();
|
||||
} else {
|
||||
status_.~Status();
|
||||
}
|
||||
}
|
||||
|
||||
void Assign(const T& value) {
|
||||
if (ok()) {
|
||||
data_.~T();
|
||||
MakeValue(value);
|
||||
} else {
|
||||
MakeValue(value);
|
||||
status_ = OkStatus();
|
||||
}
|
||||
}
|
||||
|
||||
void Assign(T&& value) {
|
||||
if (ok()) {
|
||||
data_.~T();
|
||||
MakeValue(std::move(value));
|
||||
} else {
|
||||
MakeValue(std::move(value));
|
||||
status_ = OkStatus();
|
||||
}
|
||||
}
|
||||
|
||||
void Assign(const Status& status) {
|
||||
Clear();
|
||||
status_ = status;
|
||||
EnsureNotOk();
|
||||
}
|
||||
|
||||
void Assign(Status&& status) {
|
||||
Clear();
|
||||
// Note that we copy instead of moving the status here so that
|
||||
// status.~StatusOrData() can call ok() without invoking UB.
|
||||
status_ = status;
|
||||
EnsureNotOk();
|
||||
}
|
||||
|
||||
bool ok() const { return status_.ok(); }
|
||||
|
||||
protected:
|
||||
// status_ will always be active after the constructor.
|
||||
// We make it a union to be able to initialize exactly how we need without
|
||||
// waste.
|
||||
// Eg. in the copy constructor we use the default constructor of Status in
|
||||
// the ok() path to avoid an extra Ref call.
|
||||
union {
|
||||
Status status_;
|
||||
};
|
||||
|
||||
// data_ is active iff status_.ok()==true
|
||||
struct Dummy {};
|
||||
union {
|
||||
// When T is const, we need some non-const object we can cast to void* for
|
||||
// the placement new. dummy_ is that object.
|
||||
Dummy dummy_;
|
||||
T data_;
|
||||
};
|
||||
|
||||
void Clear() {
|
||||
if (ok()) data_.~T();
|
||||
}
|
||||
|
||||
void EnsureOk() const {
|
||||
if (!ok()) Helper::Crash(status_);
|
||||
}
|
||||
|
||||
void EnsureNotOk() {
|
||||
if (ok()) Helper::HandleInvalidStatusCtorArg(&status_);
|
||||
}
|
||||
|
||||
// Construct the value (ie. data_) through placement new with the passed
|
||||
// argument.
|
||||
template <typename Arg>
|
||||
void MakeValue(Arg&& arg) {
|
||||
internal_statusor::PlacementNew<T>(&dummy_, std::forward<Arg>(arg));
|
||||
}
|
||||
|
||||
// Construct the status (ie. status_) through placement new with the passed
|
||||
// argument.
|
||||
template <typename... Args>
|
||||
void MakeStatus(Args&&... args) {
|
||||
internal_statusor::PlacementNew<Status>(&status_,
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
// Helper base class to allow implicitly deleted constructors and assignment
|
||||
// operations in StatusOr.
|
||||
// TraitsBase will explicitly delete what it can't support and StatusOr will
|
||||
// inherit that behavior implicitly.
|
||||
template <bool Copy, bool Move>
|
||||
struct TraitsBase {
|
||||
TraitsBase() = default;
|
||||
TraitsBase(const TraitsBase&) = default;
|
||||
TraitsBase(TraitsBase&&) = default;
|
||||
TraitsBase& operator=(const TraitsBase&) = default;
|
||||
TraitsBase& operator=(TraitsBase&&) = default;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TraitsBase<false, true> {
|
||||
TraitsBase() = default;
|
||||
TraitsBase(const TraitsBase&) = delete;
|
||||
TraitsBase(TraitsBase&&) = default;
|
||||
TraitsBase& operator=(const TraitsBase&) = delete;
|
||||
TraitsBase& operator=(TraitsBase&&) = default;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TraitsBase<false, false> {
|
||||
TraitsBase() = default;
|
||||
TraitsBase(const TraitsBase&) = delete;
|
||||
TraitsBase(TraitsBase&&) = delete;
|
||||
TraitsBase& operator=(const TraitsBase&) = delete;
|
||||
TraitsBase& operator=(TraitsBase&&) = delete;
|
||||
};
|
||||
|
||||
} // namespace internal_statusor
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_STATUS_STATUSOR_INTERNALS_H_
|
||||
Loading…
Add table
Add a link
Reference in a new issue