/proc/self/cwd/common/internal/reference_count.cc
Line | Count | Source |
1 | | // Copyright 2024 Google LLC |
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 | | // https://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 | | #include "common/internal/reference_count.h" |
16 | | |
17 | | #include <cstddef> |
18 | | #include <cstring> |
19 | | #include <memory> |
20 | | #include <new> |
21 | | #include <string> |
22 | | #include <utility> |
23 | | |
24 | | #include "absl/base/nullability.h" |
25 | | #include "absl/log/absl_check.h" |
26 | | #include "absl/strings/string_view.h" |
27 | | #include "common/data.h" |
28 | | #include "internal/new.h" |
29 | | #include "google/protobuf/message_lite.h" |
30 | | |
31 | | namespace cel::common_internal { |
32 | | |
33 | | template class DeletingReferenceCount<google::protobuf::MessageLite>; |
34 | | |
35 | | namespace { |
36 | | |
37 | | class ReferenceCountedStdString final : public ReferenceCounted { |
38 | | public: |
39 | | static std::pair<const ReferenceCount* absl_nonnull, absl::string_view> New( |
40 | 2 | std::string&& string) { |
41 | 2 | const auto* const refcount = |
42 | 2 | new ReferenceCountedStdString(std::move(string)); |
43 | 2 | const auto* const refcount_string = std::launder( |
44 | 2 | reinterpret_cast<const std::string*>(&refcount->string_[0])); |
45 | 2 | return std::pair{static_cast<const ReferenceCount* absl_nonnull>(refcount), |
46 | 2 | absl::string_view(*refcount_string)}; |
47 | 2 | } |
48 | | |
49 | 2 | explicit ReferenceCountedStdString(std::string&& string) { |
50 | 2 | (::new (static_cast<void*>(&string_[0])) std::string(std::move(string))) |
51 | 2 | ->shrink_to_fit(); |
52 | 2 | } |
53 | | |
54 | | private: |
55 | 2 | void Finalize() noexcept override { |
56 | 2 | std::destroy_at(std::launder(reinterpret_cast<std::string*>(&string_[0]))); |
57 | 2 | } |
58 | | |
59 | | alignas(std::string) char string_[sizeof(std::string)]; |
60 | | }; |
61 | | |
62 | | class ReferenceCountedString final : public ReferenceCounted { |
63 | | public: |
64 | | static std::pair<const ReferenceCount* absl_nonnull, absl::string_view> New( |
65 | 5.46k | absl::string_view string) { |
66 | 5.46k | const auto* const refcount = |
67 | 5.46k | ::new (internal::New(Overhead() + string.size())) |
68 | 5.46k | ReferenceCountedString(string); |
69 | 5.46k | return std::pair{static_cast<const ReferenceCount* absl_nonnull>(refcount), |
70 | 5.46k | absl::string_view(refcount->data_, refcount->size_)}; |
71 | 5.46k | } |
72 | | |
73 | | private: |
74 | | // ReferenceCountedString is non-standard-layout due to having virtual functions |
75 | | // from a base class. This causes compilers to warn about the use of offsetof(), |
76 | | // but it still works here, so silence the warning and proceed. |
77 | | #if defined(__GNUC__) || defined(__clang__) |
78 | | #pragma GCC diagnostic push |
79 | | #pragma GCC diagnostic ignored "-Winvalid-offsetof" |
80 | | #endif |
81 | | |
82 | 10.9k | static size_t Overhead() { return offsetof(ReferenceCountedString, data_); } |
83 | | |
84 | | #if defined(__GNUC__) || defined(__clang__) |
85 | | #pragma GCC diagnostic pop |
86 | | #endif |
87 | | |
88 | | explicit ReferenceCountedString(absl::string_view string) |
89 | 5.46k | : size_(string.size()) { |
90 | 5.46k | std::memcpy(data_, string.data(), size_); |
91 | 5.46k | } |
92 | | |
93 | 5.46k | void Delete() noexcept override { |
94 | 5.46k | void* const that = this; |
95 | 5.46k | const auto size = size_; |
96 | 5.46k | std::destroy_at(this); |
97 | 5.46k | internal::SizedDelete(that, Overhead() + size); |
98 | 5.46k | } |
99 | | |
100 | | const size_t size_; |
101 | | char data_[]; |
102 | | }; |
103 | | |
104 | | } // namespace |
105 | | |
106 | | std::pair<const ReferenceCount* absl_nonnull, absl::string_view> |
107 | 5.46k | MakeReferenceCountedString(absl::string_view value) { |
108 | 5.46k | ABSL_DCHECK(!value.empty()); |
109 | 5.46k | return ReferenceCountedString::New(value); |
110 | 5.46k | } |
111 | | |
112 | | std::pair<const ReferenceCount* absl_nonnull, absl::string_view> |
113 | 2 | MakeReferenceCountedString(std::string&& value) { |
114 | 2 | ABSL_DCHECK(!value.empty()); |
115 | 2 | return ReferenceCountedStdString::New(std::move(value)); |
116 | 2 | } |
117 | | |
118 | | } // namespace cel::common_internal |