OLD | NEW |
1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
4 // | 4 // |
5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
7 // met: | 7 // met: |
8 // | 8 // |
9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
(...skipping 22 matching lines...) Expand all Loading... |
33 // representation to be made more space-efficient via various optimizations. | 33 // representation to be made more space-efficient via various optimizations. |
34 // | 34 // |
35 // Note that this is distinct from google::protobuf::Metadata, which encapsulate
s | 35 // Note that this is distinct from google::protobuf::Metadata, which encapsulate
s |
36 // Descriptor and Reflection pointers. | 36 // Descriptor and Reflection pointers. |
37 | 37 |
38 #ifndef GOOGLE_PROTOBUF_METADATA_H__ | 38 #ifndef GOOGLE_PROTOBUF_METADATA_H__ |
39 #define GOOGLE_PROTOBUF_METADATA_H__ | 39 #define GOOGLE_PROTOBUF_METADATA_H__ |
40 | 40 |
41 #include <google/protobuf/stubs/common.h> | 41 #include <google/protobuf/stubs/common.h> |
42 #include <google/protobuf/arena.h> | 42 #include <google/protobuf/arena.h> |
43 #include <google/protobuf/arenastring.h> | |
44 #include <google/protobuf/generated_message_util.h> | |
45 #include <google/protobuf/unknown_field_set.h> | 43 #include <google/protobuf/unknown_field_set.h> |
46 | 44 |
47 namespace google { | 45 namespace google { |
48 namespace protobuf { | 46 namespace protobuf { |
49 namespace internal { | 47 namespace internal { |
50 | 48 |
51 // This is the representation for messages that support arena allocation. It | 49 // This is the representation for messages that support arena allocation. It |
52 // uses a tagged pointer to either store the Arena pointer, if there are no | 50 // uses a tagged pointer to either store the Arena pointer, if there are no |
53 // unknown fields, or a pointer to a block of memory with both the Arena pointer | 51 // unknown fields, or a pointer to a block of memory with both the Arena pointer |
54 // and the UnknownFieldSet, if there are unknown fields. This optimization | 52 // and the UnknownFieldSet, if there are unknown fields. This optimization |
55 // allows for "zero-overhead" storage of the Arena pointer, relative to the | 53 // allows for "zero-overhead" storage of the Arena pointer, relative to the |
56 // above baseline implementation. | 54 // above baseline implementation. |
57 // | 55 // |
58 // The tagged pointer uses the LSB to disambiguate cases, and uses bit 0 == 0 to | 56 // The tagged pointer uses the LSB to disambiguate cases, and uses bit 0 == 0 to |
59 // indicate an arena pointer and bit 0 == 1 to indicate a UFS+Arena-container | 57 // indicate an arena pointer and bit 0 == 1 to indicate a UFS+Arena-container |
60 // pointer. | 58 // pointer. |
61 template <class T, class Derived> | 59 class LIBPROTOBUF_EXPORT InternalMetadataWithArena { |
62 class InternalMetadataWithArenaBase { | |
63 public: | 60 public: |
64 InternalMetadataWithArenaBase() : ptr_(NULL) {} | 61 InternalMetadataWithArena() : ptr_(NULL) {} |
65 explicit InternalMetadataWithArenaBase(Arena* arena) : ptr_(arena) {} | 62 explicit InternalMetadataWithArena(Arena* arena) |
| 63 : ptr_ (arena) {} |
66 | 64 |
67 ~InternalMetadataWithArenaBase() { | 65 ~InternalMetadataWithArena() { |
68 if (have_unknown_fields() && arena() == NULL) { | 66 if (have_unknown_fields() && arena() == NULL) { |
69 delete PtrValue<Container>(); | 67 delete PtrValue<Container>(); |
70 } | 68 } |
71 ptr_ = NULL; | 69 ptr_ = NULL; |
72 } | 70 } |
73 | 71 |
74 GOOGLE_ATTRIBUTE_ALWAYS_INLINE const T& unknown_fields() const { | 72 GOOGLE_ATTRIBUTE_ALWAYS_INLINE const UnknownFieldSet& unknown_fields() const { |
75 if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) { | 73 if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) { |
76 return PtrValue<Container>()->unknown_fields; | 74 return PtrValue<Container>()->unknown_fields_; |
77 } else { | 75 } else { |
78 return Derived::default_instance(); | 76 return *UnknownFieldSet::default_instance(); |
79 } | 77 } |
80 } | 78 } |
81 | 79 |
82 GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* mutable_unknown_fields() { | 80 GOOGLE_ATTRIBUTE_ALWAYS_INLINE UnknownFieldSet* mutable_unknown_fields() { |
83 if (GOOGLE_PREDICT_TRUE(have_unknown_fields())) { | 81 if (GOOGLE_PREDICT_TRUE(have_unknown_fields())) { |
84 return &PtrValue<Container>()->unknown_fields; | 82 return &PtrValue<Container>()->unknown_fields_; |
85 } else { | 83 } else { |
86 return mutable_unknown_fields_slow(); | 84 return mutable_unknown_fields_slow(); |
87 } | 85 } |
88 } | 86 } |
89 | 87 |
90 GOOGLE_ATTRIBUTE_ALWAYS_INLINE Arena* arena() const { | 88 GOOGLE_ATTRIBUTE_ALWAYS_INLINE Arena* arena() const { |
91 if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) { | 89 if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) { |
92 return PtrValue<Container>()->arena; | 90 return PtrValue<Container>()->arena_; |
93 } else { | 91 } else { |
94 return PtrValue<Arena>(); | 92 return PtrValue<Arena>(); |
95 } | 93 } |
96 } | 94 } |
97 | 95 |
98 GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool have_unknown_fields() const { | 96 GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool have_unknown_fields() const { |
99 return PtrTag() == kTagContainer; | 97 return PtrTag() == kTagContainer; |
100 } | 98 } |
101 | 99 |
102 GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(Derived* other) { | 100 GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(InternalMetadataWithArena* other) { |
103 // Semantics here are that we swap only the unknown fields, not the arena | 101 // Semantics here are that we swap only the unknown fields, not the arena |
104 // pointer. We cannot simply swap ptr_ with other->ptr_ because we need to | 102 // pointer. We cannot simply swap ptr_ with other->ptr_ because we need to |
105 // maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in | 103 // maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in |
106 // different states (direct arena pointer vs. container with UFS) so we | 104 // different states (direct arena pointer vs. container with UFS) so we |
107 // cannot simply swap ptr_ and then restore the arena pointers. We reuse | 105 // cannot simply swap ptr_ and then restore the arena pointers. We reuse |
108 // UFS's swap implementation instead. | 106 // UFS's swap implementation instead. |
109 if (have_unknown_fields() || other->have_unknown_fields()) { | 107 if (have_unknown_fields() || other->have_unknown_fields()) { |
110 static_cast<Derived*>(this)->DoSwap(other->mutable_unknown_fields()); | 108 mutable_unknown_fields()->Swap(other->mutable_unknown_fields()); |
111 } | 109 } |
112 } | 110 } |
113 | 111 |
114 GOOGLE_ATTRIBUTE_ALWAYS_INLINE void MergeFrom(const Derived& other) { | |
115 if (other.have_unknown_fields()) { | |
116 static_cast<Derived*>(this)->DoMergeFrom(other.unknown_fields()); | |
117 } | |
118 } | |
119 | |
120 GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Clear() { | |
121 if (have_unknown_fields()) { | |
122 static_cast<Derived*>(this)->DoClear(); | |
123 } | |
124 } | |
125 | |
126 GOOGLE_ATTRIBUTE_ALWAYS_INLINE void* raw_arena_ptr() const { | 112 GOOGLE_ATTRIBUTE_ALWAYS_INLINE void* raw_arena_ptr() const { |
127 return ptr_; | 113 return ptr_; |
128 } | 114 } |
129 | 115 |
130 private: | 116 private: |
131 void* ptr_; | 117 void* ptr_; |
132 | 118 |
133 // Tagged pointer implementation. | 119 // Tagged pointer implementation. |
134 enum { | 120 enum { |
135 // ptr_ is an Arena*. | 121 // ptr_ is an Arena*. |
136 kTagArena = 0, | 122 kTagArena = 0, |
137 // ptr_ is a Container*. | 123 // ptr_ is a Container*. |
138 kTagContainer = 1, | 124 kTagContainer = 1, |
139 }; | 125 }; |
140 static const intptr_t kPtrTagMask = 1; | 126 static const intptr_t kPtrTagMask = 1; |
141 static const intptr_t kPtrValueMask = ~kPtrTagMask; | 127 static const intptr_t kPtrValueMask = ~kPtrTagMask; |
142 | 128 |
143 // Accessors for pointer tag and pointer value. | 129 // Accessors for pointer tag and pointer value. |
144 GOOGLE_ATTRIBUTE_ALWAYS_INLINE int PtrTag() const { | 130 GOOGLE_ATTRIBUTE_ALWAYS_INLINE int PtrTag() const { |
145 return reinterpret_cast<intptr_t>(ptr_) & kPtrTagMask; | 131 return reinterpret_cast<intptr_t>(ptr_) & kPtrTagMask; |
146 } | 132 } |
147 | 133 |
148 template<typename U> U* PtrValue() const { | 134 template<typename T> T* PtrValue() const { |
149 return reinterpret_cast<U*>( | 135 return reinterpret_cast<T*>( |
150 reinterpret_cast<intptr_t>(ptr_) & kPtrValueMask); | 136 reinterpret_cast<intptr_t>(ptr_) & kPtrValueMask); |
151 } | 137 } |
152 | 138 |
153 // If ptr_'s tag is kTagContainer, it points to an instance of this struct. | 139 // If ptr_'s tag is kTagContainer, it points to an instance of this struct. |
154 struct Container { | 140 struct Container { |
155 T unknown_fields; | 141 UnknownFieldSet unknown_fields_; |
156 Arena* arena; | 142 Arena* arena_; |
157 }; | 143 }; |
158 | 144 |
159 GOOGLE_ATTRIBUTE_NOINLINE T* mutable_unknown_fields_slow() { | 145 GOOGLE_ATTRIBUTE_NOINLINE UnknownFieldSet* mutable_unknown_fields_slow() { |
160 Arena* my_arena = arena(); | 146 Arena* my_arena = arena(); |
161 Container* container = Arena::Create<Container>(my_arena); | 147 Container* container = Arena::Create<Container>(my_arena); |
162 ptr_ = reinterpret_cast<void*>( | 148 ptr_ = reinterpret_cast<void*>( |
163 reinterpret_cast<intptr_t>(container) | kTagContainer); | 149 reinterpret_cast<intptr_t>(container) | kTagContainer); |
164 container->arena = my_arena; | 150 container->arena_ = my_arena; |
165 return &(container->unknown_fields); | 151 return &(container->unknown_fields_); |
166 } | 152 } |
167 }; | 153 }; |
168 | 154 |
169 class InternalMetadataWithArena | 155 // Temporary compatibility typedef. Remove once this is released in components |
170 : public InternalMetadataWithArenaBase<UnknownFieldSet, | 156 // and upb CL is submitted. |
171 InternalMetadataWithArena> { | 157 typedef InternalMetadataWithArena InternalMetadata; |
172 public: | |
173 InternalMetadataWithArena() {} | |
174 explicit InternalMetadataWithArena(Arena* arena) | |
175 : InternalMetadataWithArenaBase(arena) {} | |
176 | |
177 void DoSwap(UnknownFieldSet* other) { | |
178 mutable_unknown_fields()->Swap(other); | |
179 } | |
180 | |
181 void DoMergeFrom(const UnknownFieldSet& other) { | |
182 mutable_unknown_fields()->MergeFrom(other); | |
183 } | |
184 | |
185 void DoClear() { | |
186 mutable_unknown_fields()->Clear(); | |
187 } | |
188 | |
189 static const UnknownFieldSet& default_instance() { | |
190 return *UnknownFieldSet::default_instance(); | |
191 } | |
192 }; | |
193 | |
194 // We store unknown fields as a string right now, because there is currently no | |
195 // good interface for reading unknown fields into an ArenaString. We may want | |
196 // to revisit this to allow unknown fields to be parsed onto the Arena. | |
197 class InternalMetadataWithArenaLite | |
198 : public InternalMetadataWithArenaBase<string, | |
199 InternalMetadataWithArenaLite> { | |
200 public: | |
201 InternalMetadataWithArenaLite() {} | |
202 | |
203 explicit InternalMetadataWithArenaLite(Arena* arena) | |
204 : InternalMetadataWithArenaBase(arena) {} | |
205 | |
206 void DoSwap(string* other) { | |
207 mutable_unknown_fields()->swap(*other); | |
208 } | |
209 | |
210 void DoMergeFrom(const string& other) { | |
211 mutable_unknown_fields()->append(other); | |
212 } | |
213 | |
214 void DoClear() { | |
215 mutable_unknown_fields()->clear(); | |
216 } | |
217 | |
218 static const string& default_instance() { | |
219 return GetEmptyStringAlreadyInited(); | |
220 } | |
221 }; | |
222 | 158 |
223 } // namespace internal | 159 } // namespace internal |
224 } // namespace protobuf | 160 } // namespace protobuf |
225 | 161 |
226 } // namespace google | 162 } // namespace google |
227 #endif // GOOGLE_PROTOBUF_METADATA_H__ | 163 #endif // GOOGLE_PROTOBUF_METADATA_H__ |
OLD | NEW |