Skip to content

Commit 065815b

Browse files
jckingcopybara-github
authored andcommitted
Make cel::AttributeSet copy-on-write
PiperOrigin-RevId: 985421843
1 parent 354bca8 commit 065815b

12 files changed

Lines changed: 151 additions & 80 deletions

base/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ cc_library(
3535
":kind",
3636
"//internal:status_macros",
3737
"@com_google_absl//absl/base:core_headers",
38+
"@com_google_absl//absl/base:no_destructor",
3839
"@com_google_absl//absl/base:nullability",
3940
"@com_google_absl//absl/container:btree",
4041
"@com_google_absl//absl/status",

base/attribute_set.h

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
#ifndef THIRD_PARTY_CEL_CPP_BASE_ATTRIBUTE_SET_H_
1616
#define THIRD_PARTY_CEL_CPP_BASE_ATTRIBUTE_SET_H_
1717

18+
#include <memory>
19+
20+
#include "absl/base/no_destructor.h"
1821
#include "absl/container/btree_set.h"
1922
#include "absl/types/span.h"
2023
#include "base/attribute.h"
@@ -54,27 +57,43 @@ class AttributeSet final {
5457
}
5558
}
5659

57-
AttributeSet(const AttributeSet& set1, const AttributeSet& set2)
58-
: attributes_(set1.attributes_) {
59-
for (const auto& attr : set2.attributes_) {
60-
Add(attr);
61-
}
60+
AttributeSet(const AttributeSet& set1, const AttributeSet& set2) {
61+
Add(set1);
62+
Add(set2);
6263
}
6364

64-
iterator begin() const { return attributes_.begin(); }
65+
iterator begin() const {
66+
return attributes_ != nullptr ? attributes_->begin()
67+
: EmptyContainer().begin();
68+
}
6569

66-
const_iterator cbegin() const { return attributes_.cbegin(); }
70+
const_iterator cbegin() const {
71+
return attributes_ != nullptr ? attributes_->cbegin()
72+
: EmptyContainer().cbegin();
73+
}
6774

68-
iterator end() const { return attributes_.end(); }
75+
iterator end() const {
76+
return attributes_ != nullptr ? attributes_->end() : EmptyContainer().end();
77+
}
6978

70-
const_iterator cend() const { return attributes_.cend(); }
79+
const_iterator cend() const {
80+
return attributes_ != nullptr ? attributes_->cend()
81+
: EmptyContainer().cend();
82+
}
7183

72-
size_type size() const { return attributes_.size(); }
84+
size_type size() const {
85+
return attributes_ != nullptr ? attributes_->size() : 0;
86+
}
7387

74-
bool empty() const { return attributes_.empty(); }
88+
bool empty() const { return attributes_ == nullptr || attributes_->empty(); }
7589

7690
bool operator==(const AttributeSet& other) const {
77-
return this == &other || attributes_ == other.attributes_;
91+
if (attributes_ == other.attributes_) {
92+
return true;
93+
}
94+
return (attributes_ != nullptr ? *attributes_ : EmptyContainer()) ==
95+
(other.attributes_ != nullptr ? *other.attributes_
96+
: EmptyContainer());
7897
}
7998

8099
bool operator!=(const AttributeSet& other) const {
@@ -91,16 +110,31 @@ class AttributeSet final {
91110
friend class UnknownValue;
92111
friend class base_internal::UnknownSet;
93112

94-
void Add(const Attribute& attribute) { attributes_.insert(attribute); }
113+
static const Container& EmptyContainer() {
114+
static const absl::NoDestructor<Container> container;
115+
return *container;
116+
}
117+
118+
void Add(const Attribute& attribute) {
119+
if (attributes_ == nullptr) {
120+
attributes_ = std::make_shared<Container>();
121+
}
122+
attributes_->insert(attribute);
123+
}
95124

96125
void Add(const AttributeSet& other) {
97-
for (const auto& attribute : other) {
98-
Add(attribute);
126+
if (!other.empty()) {
127+
if (attributes_ == nullptr) {
128+
attributes_ = std::make_shared<Container>();
129+
}
130+
for (const auto& attribute : other) {
131+
attributes_->insert(attribute);
132+
}
99133
}
100134
}
101135

102136
// Attribute container.
103-
Container attributes_;
137+
std::shared_ptr<Container> attributes_;
104138
};
105139

106140
} // namespace cel

common/legacy_value.cc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,7 +1073,8 @@ absl::Status ModernValue(google::protobuf::Arena* arena,
10731073
MapValue(common_internal::LegacyMapValue(legacy_value.MapOrDie()));
10741074
return absl::OkStatus();
10751075
case CelValue::Type::kUnknownSet:
1076-
result = UnknownValue{*legacy_value.UnknownSetOrDie()};
1076+
result =
1077+
common_internal::MakeUnknownValue(*legacy_value.UnknownSetOrDie());
10771078
return absl::OkStatus();
10781079
case CelValue::Type::kCelType: {
10791080
auto type_name = legacy_value.CelTypeOrDie().value();
@@ -1132,7 +1133,8 @@ absl::StatusOr<google::api::expr::runtime::CelValue> LegacyValue(
11321133
return common_internal::LegacyTrivialMapValue(arena, modern_value);
11331134
case ValueKind::kUnknown:
11341135
return CelValue::CreateUnknownSet(google::protobuf::Arena::Create<Unknown>(
1135-
arena, Cast<UnknownValue>(modern_value).NativeValue()));
1136+
arena,
1137+
common_internal::GetUnknown(Cast<UnknownValue>(modern_value))));
11361138
case ValueKind::kType:
11371139
return CelValue::CreateCelType(
11381140
CelValue::CelTypeHolder(google::protobuf::Arena::Create<std::string>(
@@ -1185,7 +1187,7 @@ absl::StatusOr<Value> FromLegacyValue(google::protobuf::Arena* arena,
11851187
case CelValue::Type::kMap:
11861188
return MapValue(common_internal::LegacyMapValue(legacy_value.MapOrDie()));
11871189
case CelValue::Type::kUnknownSet:
1188-
return UnknownValue{*legacy_value.UnknownSetOrDie()};
1190+
return common_internal::MakeUnknownValue(*legacy_value.UnknownSetOrDie());
11891191
case CelValue::Type::kCelType:
11901192
return CreateTypeValueFromView(arena,
11911193
legacy_value.CelTypeOrDie().value());
@@ -1236,7 +1238,7 @@ absl::StatusOr<google::api::expr::runtime::CelValue> ToLegacyValue(
12361238
return common_internal::LegacyTrivialMapValue(arena, value);
12371239
case ValueKind::kUnknown:
12381240
return CelValue::CreateUnknownSet(google::protobuf::Arena::Create<Unknown>(
1239-
arena, Cast<UnknownValue>(value).NativeValue()));
1241+
arena, common_internal::GetUnknown(Cast<UnknownValue>(value))));
12401242
case ValueKind::kType:
12411243
return CelValue::CreateCelType(
12421244
CelValue::CelTypeHolder(google::protobuf::Arena::Create<std::string>(

common/values/unknown_value.h

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,21 @@ namespace cel {
4040
class Value;
4141
class UnknownValue;
4242

43+
namespace common_internal {
44+
[[nodiscard]]
45+
UnknownValue MakeUnknownValue(Unknown value);
46+
[[nodiscard]]
47+
Unknown GetUnknown(const UnknownValue& value);
48+
[[nodiscard]]
49+
const FunctionResultSet& GetUnknownFunctionResultSet(
50+
const UnknownValue& value ABSL_ATTRIBUTE_LIFETIME_BOUND);
51+
} // namespace common_internal
52+
4353
// `UnknownValue` represents values of the primitive `duration` type.
4454
class UnknownValue final : private common_internal::ValueMixin<UnknownValue> {
4555
public:
4656
static constexpr ValueKind kKind = ValueKind::kUnknown;
4757

48-
explicit UnknownValue(Unknown unknown) : unknown_(std::move(unknown)) {}
49-
5058
UnknownValue() = default;
5159
UnknownValue(const UnknownValue&) = default;
5260
UnknownValue(UnknownValue&&) = default;
@@ -80,31 +88,25 @@ class UnknownValue final : private common_internal::ValueMixin<UnknownValue> {
8088

8189
bool IsZeroValue() const { return false; }
8290

83-
void swap(UnknownValue& other) noexcept {
84-
using std::swap;
85-
swap(unknown_, other.unknown_);
86-
}
87-
88-
const Unknown& NativeValue() const& ABSL_ATTRIBUTE_LIFETIME_BOUND {
89-
return unknown_;
90-
}
91-
92-
Unknown NativeValue() && {
93-
Unknown unknown = std::move(unknown_);
94-
return unknown;
95-
}
96-
97-
const AttributeSet& attribute_set() const {
91+
[[nodiscard]]
92+
AttributeSet ToAttributeSet() const {
9893
return unknown_.unknown_attributes();
9994
}
10095

101-
const FunctionResultSet& function_result_set() const {
102-
return unknown_.unknown_function_results();
96+
void swap(UnknownValue& other) noexcept {
97+
using std::swap;
98+
swap(unknown_, other.unknown_);
10399
}
104100

105101
private:
102+
friend UnknownValue common_internal::MakeUnknownValue(Unknown value);
103+
friend Unknown common_internal::GetUnknown(const UnknownValue&);
104+
friend const FunctionResultSet& common_internal::GetUnknownFunctionResultSet(
105+
const UnknownValue& value);
106106
friend class common_internal::ValueMixin<UnknownValue>;
107107

108+
explicit UnknownValue(Unknown unknown) : unknown_(std::move(unknown)) {}
109+
108110
Unknown unknown_;
109111
};
110112

@@ -116,6 +118,26 @@ inline std::ostream& operator<<(std::ostream& out, const UnknownValue& value) {
116118
return out << value.DebugString();
117119
}
118120

121+
namespace common_internal {
122+
123+
[[nodiscard]]
124+
inline UnknownValue MakeUnknownValue(Unknown value) {
125+
return UnknownValue(std::move(value));
126+
}
127+
128+
[[nodiscard]]
129+
inline Unknown GetUnknown(const UnknownValue& value) {
130+
return value.unknown_;
131+
}
132+
133+
[[nodiscard]]
134+
inline const FunctionResultSet& GetUnknownFunctionResultSet(
135+
const UnknownValue& value ABSL_ATTRIBUTE_LIFETIME_BOUND) {
136+
return value.unknown_.unknown_function_results();
137+
}
138+
139+
} // namespace common_internal
140+
119141
} // namespace cel
120142

121143
#endif // THIRD_PARTY_CEL_CPP_COMMON_VALUES_UNKNOWN_VALUE_H_

eval/eval/attribute_utility.cc

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,19 @@ absl::optional<UnknownValue> AttributeUtility::MergeUnknowns(
118118
const auto& current_set = value.GetUnknown();
119119

120120
cel::base_internal::UnknownSetAccess::Add(
121-
*result_set, UnknownSet(current_set.attribute_set(),
122-
current_set.function_result_set()));
121+
*result_set,
122+
UnknownSet(
123+
current_set.ToAttributeSet(),
124+
cel::common_internal::GetUnknownFunctionResultSet(current_set)));
123125
}
124126

125127
if (!result_set.has_value()) {
126128
return std::nullopt;
127129
}
128130

129-
return UnknownValue(cel::Unknown(result_set->unknown_attributes(),
130-
result_set->unknown_function_results()));
131+
return cel::common_internal::MakeUnknownValue(
132+
cel::Unknown(result_set->unknown_attributes(),
133+
result_set->unknown_function_results()));
131134
}
132135

133136
UnknownValue AttributeUtility::MergeUnknownValues(
@@ -136,12 +139,13 @@ UnknownValue AttributeUtility::MergeUnknownValues(
136139
// distinguish unset (nullopt) and empty(engaged empty value).
137140
AttributeSet attributes;
138141
FunctionResultSet function_results;
139-
attributes.Add(left.attribute_set());
140-
function_results.Add(left.function_result_set());
141-
attributes.Add(right.attribute_set());
142-
function_results.Add(right.function_result_set());
142+
attributes.Add(left.ToAttributeSet());
143+
function_results.Add(cel::common_internal::GetUnknownFunctionResultSet(left));
144+
attributes.Add(right.ToAttributeSet());
145+
function_results.Add(
146+
cel::common_internal::GetUnknownFunctionResultSet(right));
143147

144-
return UnknownValue(
148+
return cel::common_internal::MakeUnknownValue(
145149
cel::Unknown(std::move(attributes), std::move(function_results)));
146150
}
147151

@@ -191,16 +195,17 @@ absl::optional<UnknownValue> AttributeUtility::IdentifyAndMergeUnknowns(
191195

192196
if (arg_unknowns.has_value()) {
193197
cel::base_internal::UnknownSetAccess::Add(
194-
*result_set, UnknownSet((*arg_unknowns).attribute_set(),
195-
(*arg_unknowns).function_result_set()));
198+
*result_set, cel::common_internal::GetUnknown(*arg_unknowns));
196199
}
197200

198-
return UnknownValue(cel::Unknown(result_set->unknown_attributes(),
199-
result_set->unknown_function_results()));
201+
return cel::common_internal::MakeUnknownValue(
202+
cel::Unknown(result_set->unknown_attributes(),
203+
result_set->unknown_function_results()));
200204
}
201205

202206
UnknownValue AttributeUtility::CreateUnknownSet(cel::Attribute attr) const {
203-
return UnknownValue(cel::Unknown(AttributeSet({std::move(attr)})));
207+
return cel::common_internal::MakeUnknownValue(
208+
cel::Unknown(AttributeSet({std::move(attr)})));
204209
}
205210

206211
absl::StatusOr<ErrorValue> AttributeUtility::CreateMissingAttributeError(
@@ -213,13 +218,14 @@ absl::StatusOr<ErrorValue> AttributeUtility::CreateMissingAttributeError(
213218
UnknownValue AttributeUtility::CreateUnknownSet(
214219
const cel::FunctionDescriptor& fn_descriptor, int64_t expr_id,
215220
absl::Span<const cel::Value> args) const {
216-
return UnknownValue(
221+
return cel::common_internal::MakeUnknownValue(
217222
cel::Unknown(FunctionResultSet(FunctionResult(fn_descriptor, expr_id))));
218223
}
219224

220225
void AttributeUtility::Add(Accumulator& a, const cel::UnknownValue& v) const {
221-
a.attribute_set_.Add(v.attribute_set());
222-
a.function_result_set_.Add(v.function_result_set());
226+
a.attribute_set_.Add(v.ToAttributeSet());
227+
a.function_result_set_.Add(
228+
cel::common_internal::GetUnknownFunctionResultSet(v));
223229
}
224230

225231
void AttributeUtility::Add(Accumulator& a, const AttributeTrail& attr) const {
@@ -253,7 +259,7 @@ bool Accumulator::IsEmpty() const {
253259
}
254260

255261
cel::UnknownValue Accumulator::Build() && {
256-
return cel::UnknownValue(
262+
return cel::common_internal::MakeUnknownValue(
257263
cel::Unknown(std::move(attribute_set_), std::move(function_result_set_)));
258264
}
259265

eval/eval/attribute_utility_test.cc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,10 @@ TEST_F(AttributeUtilityTest, UnknownsUtilityMergeUnknownsFromValues) {
8585

8686
AttributeUtility utility(unknown_patterns, missing_attribute_patterns);
8787

88-
UnknownValue unknown_set0 =
89-
cel::UnknownValue(cel::Unknown(AttributeSet({attribute0})));
90-
UnknownValue unknown_set1 =
91-
cel::UnknownValue(cel::Unknown(AttributeSet({attribute1})));
88+
UnknownValue unknown_set0 = cel::common_internal::MakeUnknownValue(
89+
cel::Unknown(AttributeSet({attribute0})));
90+
UnknownValue unknown_set1 = cel::common_internal::MakeUnknownValue(
91+
cel::Unknown(AttributeSet({attribute1})));
9292

9393
std::vector<cel::Value> values = {
9494
unknown_set0,
@@ -99,7 +99,7 @@ TEST_F(AttributeUtilityTest, UnknownsUtilityMergeUnknownsFromValues) {
9999

100100
absl::optional<UnknownValue> unknown_set = utility.MergeUnknowns(values);
101101
ASSERT_TRUE(unknown_set.has_value());
102-
EXPECT_THAT((*unknown_set).attribute_set(),
102+
EXPECT_THAT((*unknown_set).ToAttributeSet(),
103103
UnorderedPointwise(
104104
Eq(), std::vector<CelAttribute>{attribute0, attribute1}));
105105
}
@@ -162,8 +162,8 @@ TEST_F(AttributeUtilityTest, CreateUnknownSet) {
162162
AttributeUtility utility(empty_patterns, empty_patterns);
163163

164164
UnknownValue set = utility.CreateUnknownSet(trail.attribute());
165-
ASSERT_THAT(set.attribute_set(), SizeIs(1));
166-
ASSERT_OK_AND_ASSIGN(auto elem, set.attribute_set().begin()->AsString());
165+
ASSERT_THAT(set.ToAttributeSet(), SizeIs(1));
166+
ASSERT_OK_AND_ASSIGN(auto elem, set.ToAttributeSet().begin()->AsString());
167167
EXPECT_EQ(elem, "destination.ip");
168168
}
169169

0 commit comments

Comments
 (0)