diff options
author | 2023-09-17 22:03:34 -0700 | |
---|---|---|
committer | 2023-09-17 22:04:27 -0700 | |
commit | 243b7d386a15b88dfa32eeadabeb3ddc396a37f4 (patch) | |
tree | 66c563d80cf164b8cd31d8682ab013d0d840ce67 /absl/status/status.h | |
parent | 2c1e7e3c5c71891735f21302fb339e0d6edcd94c (diff) |
Change absl::Status implementation to be amenable to [[clang:trivial_abi]] annotation.
This moves the implementation of most methods from absl::Status to absl::status_internal::StatusRep, and ensures that no calls to absl::Status methods are in a cc file.
Stub implementations checking only inlined rep properties and calling no-op (RepToPointer) or out of line methods exist in status.h
PiperOrigin-RevId: 566187430
Change-Id: I356ec29c0970ffe82eac2a5d98850e647fcd5ea5
Diffstat (limited to 'absl/status/status.h')
-rw-r--r-- | absl/status/status.h | 113 |
1 files changed, 71 insertions, 42 deletions
diff --git a/absl/status/status.h b/absl/status/status.h index 2dac2fea..2f03bb64 100644 --- a/absl/status/status.h +++ b/absl/status/status.h @@ -59,10 +59,12 @@ #include "absl/base/attributes.h" #include "absl/base/config.h" +#include "absl/base/macros.h" #include "absl/base/optimization.h" #include "absl/functional/function_ref.h" #include "absl/status/internal/status_internal.h" #include "absl/strings/cord.h" +#include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" @@ -607,18 +609,15 @@ class Status final { // code, and an empty error message. explicit Status(absl::StatusCode code); - static void UnrefNonInlined(uintptr_t rep); + // Underlying constructor for status from a rep_. + explicit Status(uintptr_t rep) : rep_(rep) {} + static void Ref(uintptr_t rep); static void Unref(uintptr_t rep); // REQUIRES: !ok() - // Ensures rep_ is not shared with any other Status. - void PrepareToModify(); - - const status_internal::Payloads* GetPayloads() const; - status_internal::Payloads* GetPayloads(); - - static bool EqualsSlow(const absl::Status& a, const absl::Status& b); + // Ensures rep is not inlined or shared with any other Status. + static status_internal::StatusRep* PrepareToModify(uintptr_t rep); // MSVC 14.0 limitation requires the const. static constexpr const char kMovedFromString[] = @@ -629,24 +628,24 @@ class Status final { // Returns whether rep contains an inlined representation. // See rep_ for details. - static bool IsInlined(uintptr_t rep); + static constexpr bool IsInlined(uintptr_t rep); // Indicates whether this Status was the rhs of a move operation. See rep_ // for details. - static bool IsMovedFrom(uintptr_t rep); - static uintptr_t MovedFromRep(); + static constexpr bool IsMovedFrom(uintptr_t rep); + static constexpr uintptr_t MovedFromRep(); // Convert between error::Code and the inlined uintptr_t representation used // by rep_. See rep_ for details. - static uintptr_t CodeToInlinedRep(absl::StatusCode code); - static absl::StatusCode InlinedRepToCode(uintptr_t rep); + static constexpr uintptr_t CodeToInlinedRep(absl::StatusCode code); + static constexpr absl::StatusCode InlinedRepToCode(uintptr_t rep); // Converts between StatusRep* and the external uintptr_t representation used // by rep_. See rep_ for details. static uintptr_t PointerToRep(status_internal::StatusRep* r); - static status_internal::StatusRep* RepToPointer(uintptr_t r); + static const status_internal::StatusRep* RepToPointer(uintptr_t r); - std::string ToStringSlow(StatusToStringMode mode) const; + static std::string ToStringSlow(uintptr_t rep, StatusToStringMode mode); // Status supports two different representations. // - When the low bit is set it is an inlined representation. @@ -657,6 +656,8 @@ class Status final { // In this case all the data comes from a heap allocated Rep object. // rep_ is a status_internal::StatusRep* pointer to that structure. uintptr_t rep_; + + friend class status_internal::StatusRep; }; // OkStatus() @@ -760,11 +761,11 @@ Status ErrnoToStatus(int error_number, absl::string_view message); // Implementation details follow //------------------------------------------------------------------------------ -inline Status::Status() : rep_(CodeToInlinedRep(absl::StatusCode::kOk)) {} +inline Status::Status() : Status(absl::StatusCode::kOk) {} -inline Status::Status(absl::StatusCode code) : rep_(CodeToInlinedRep(code)) {} +inline Status::Status(absl::StatusCode code) : Status(CodeToInlinedRep(code)) {} -inline Status::Status(const Status& x) : rep_(x.rep_) { Ref(rep_); } +inline Status::Status(const Status& x) : Status(x.rep_) { Ref(rep_); } inline Status& Status::operator=(const Status& x) { uintptr_t old_rep = rep_; @@ -776,7 +777,7 @@ inline Status& Status::operator=(const Status& x) { return *this; } -inline Status::Status(Status&& x) noexcept : rep_(x.rep_) { +inline Status::Status(Status&& x) noexcept : Status(x.rep_) { x.rep_ = MovedFromRep(); } @@ -808,15 +809,27 @@ inline bool Status::ok() const { return rep_ == CodeToInlinedRep(absl::StatusCode::kOk); } +inline absl::StatusCode Status::code() const { + return status_internal::MapToLocalCode(raw_code()); +} + +inline int Status::raw_code() const { + if (IsInlined(rep_)) return static_cast<int>(InlinedRepToCode(rep_)); + return static_cast<int>(RepToPointer(rep_)->code()); +} + inline absl::string_view Status::message() const { return !IsInlined(rep_) - ? RepToPointer(rep_)->message + ? RepToPointer(rep_)->message() : (IsMovedFrom(rep_) ? absl::string_view(kMovedFromString) : absl::string_view()); } inline bool operator==(const Status& lhs, const Status& rhs) { - return lhs.rep_ == rhs.rep_ || Status::EqualsSlow(lhs, rhs); + if (lhs.rep_ == rhs.rep_) return true; + if (Status::IsInlined(lhs.rep_)) return false; + if (Status::IsInlined(rhs.rep_)) return false; + return *Status::RepToPointer(lhs.rep_) == *Status::RepToPointer(rhs.rep_); } inline bool operator!=(const Status& lhs, const Status& rhs) { @@ -824,7 +837,7 @@ inline bool operator!=(const Status& lhs, const Status& rhs) { } inline std::string Status::ToString(StatusToStringMode mode) const { - return ok() ? "OK" : ToStringSlow(mode); + return ok() ? "OK" : ToStringSlow(rep_, mode); } inline void Status::IgnoreError() const { @@ -836,34 +849,54 @@ inline void swap(absl::Status& a, absl::Status& b) { swap(a.rep_, b.rep_); } -inline const status_internal::Payloads* Status::GetPayloads() const { - return IsInlined(rep_) ? nullptr : RepToPointer(rep_)->payloads.get(); +inline absl::optional<absl::Cord> Status::GetPayload( + absl::string_view type_url) const { + if (IsInlined(rep_)) return absl::nullopt; + return RepToPointer(rep_)->GetPayload(type_url); } -inline status_internal::Payloads* Status::GetPayloads() { - return IsInlined(rep_) ? nullptr : RepToPointer(rep_)->payloads.get(); +inline void Status::SetPayload(absl::string_view type_url, absl::Cord payload) { + if (ok()) return; + status_internal::StatusRep* rep = PrepareToModify(rep_); + rep->SetPayload(type_url, std::move(payload)); + rep_ = PointerToRep(rep); } -inline bool Status::IsInlined(uintptr_t rep) { return (rep & 1) != 0; } - -inline bool Status::IsMovedFrom(uintptr_t rep) { return (rep & 2) != 0; } +inline bool Status::ErasePayload(absl::string_view type_url) { + if (IsInlined(rep_)) return false; + status_internal::StatusRep* rep = PrepareToModify(rep_); + auto res = rep->ErasePayload(type_url); + rep_ = res.new_rep; + return res.erased; +} -inline uintptr_t Status::MovedFromRep() { - return CodeToInlinedRep(absl::StatusCode::kInternal) | 2; +inline void Status::ForEachPayload( + absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor) + const { + if (IsInlined(rep_)) return; + RepToPointer(rep_)->ForEachPayload(visitor); } -inline uintptr_t Status::CodeToInlinedRep(absl::StatusCode code) { +constexpr bool Status::IsInlined(uintptr_t rep) { return (rep & 1) != 0; } + +constexpr bool Status::IsMovedFrom(uintptr_t rep) { return (rep & 2) != 0; } + +constexpr uintptr_t Status::CodeToInlinedRep(absl::StatusCode code) { return (static_cast<uintptr_t>(code) << 2) + 1; } -inline absl::StatusCode Status::InlinedRepToCode(uintptr_t rep) { - assert(IsInlined(rep)); +constexpr absl::StatusCode Status::InlinedRepToCode(uintptr_t rep) { + ABSL_ASSERT(IsInlined(rep)); return static_cast<absl::StatusCode>(rep >> 2); } -inline status_internal::StatusRep* Status::RepToPointer(uintptr_t rep) { +constexpr uintptr_t Status::MovedFromRep() { + return CodeToInlinedRep(absl::StatusCode::kInternal) | 2; +} + +inline const status_internal::StatusRep* Status::RepToPointer(uintptr_t rep) { assert(!IsInlined(rep)); - return reinterpret_cast<status_internal::StatusRep*>(rep); + return reinterpret_cast<const status_internal::StatusRep*>(rep); } inline uintptr_t Status::PointerToRep(status_internal::StatusRep* rep) { @@ -871,15 +904,11 @@ inline uintptr_t Status::PointerToRep(status_internal::StatusRep* rep) { } inline void Status::Ref(uintptr_t rep) { - if (!IsInlined(rep)) { - RepToPointer(rep)->ref.fetch_add(1, std::memory_order_relaxed); - } + if (!IsInlined(rep)) RepToPointer(rep)->Ref(); } inline void Status::Unref(uintptr_t rep) { - if (!IsInlined(rep)) { - UnrefNonInlined(rep); - } + if (!IsInlined(rep)) RepToPointer(rep)->Unref(); } inline Status OkStatus() { return Status(); } |