summaryrefslogtreecommitdiff
path: root/absl/status/status.h
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2023-09-17 22:03:34 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2023-09-17 22:04:27 -0700
commit243b7d386a15b88dfa32eeadabeb3ddc396a37f4 (patch)
tree66c563d80cf164b8cd31d8682ab013d0d840ce67 /absl/status/status.h
parent2c1e7e3c5c71891735f21302fb339e0d6edcd94c (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.h113
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(); }