|
|
|
@ -386,9 +386,10 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { |
|
|
|
|
template <typename TypeHandler> |
|
|
|
|
PROTOBUF_NDEBUG_INLINE void Swap(RepeatedPtrFieldBase* other) { |
|
|
|
|
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP |
|
|
|
|
if (GetArena() != nullptr && GetArena() == other->GetArena()) |
|
|
|
|
if (GetOwningArena() != nullptr && |
|
|
|
|
GetOwningArena() == other->GetOwningArena()) |
|
|
|
|
#else // PROTOBUF_FORCE_COPY_IN_SWAP
|
|
|
|
|
if (GetArena() == other->GetArena()) |
|
|
|
|
if (GetOwningArena() == other->GetOwningArena()) |
|
|
|
|
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
|
|
|
|
|
{ |
|
|
|
|
InternalSwap(other); |
|
|
|
@ -494,9 +495,10 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { |
|
|
|
|
|
|
|
|
|
template <typename TypeHandler> |
|
|
|
|
void AddCleared(Value<TypeHandler>* value) { |
|
|
|
|
ABSL_DCHECK(GetArena() == nullptr) << "AddCleared() can only be used on a " |
|
|
|
|
"RepeatedPtrField not on an arena."; |
|
|
|
|
ABSL_DCHECK(TypeHandler::GetArena(value) == nullptr) |
|
|
|
|
ABSL_DCHECK(GetOwningArena() == nullptr) |
|
|
|
|
<< "AddCleared() can only be used on a " |
|
|
|
|
"RepeatedPtrField not on an arena."; |
|
|
|
|
ABSL_DCHECK(TypeHandler::GetOwningArena(value) == nullptr) |
|
|
|
|
<< "AddCleared() can only accept values not on an arena."; |
|
|
|
|
MaybeExtend(); |
|
|
|
|
if (using_sso()) { |
|
|
|
@ -508,7 +510,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { |
|
|
|
|
|
|
|
|
|
template <typename TypeHandler> |
|
|
|
|
PROTOBUF_NODISCARD Value<TypeHandler>* ReleaseCleared() { |
|
|
|
|
ABSL_DCHECK(GetArena() == nullptr) |
|
|
|
|
ABSL_DCHECK(GetOwningArena() == nullptr) |
|
|
|
|
<< "ReleaseCleared() can only be used on a RepeatedPtrField not on " |
|
|
|
|
<< "an arena."; |
|
|
|
|
ABSL_DCHECK(tagged_rep_or_elem_ != nullptr); |
|
|
|
@ -525,8 +527,8 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { |
|
|
|
|
// AddAllocated version that implements arena-safe copying behavior.
|
|
|
|
|
template <typename TypeHandler> |
|
|
|
|
void AddAllocatedInternal(Value<TypeHandler>* value, std::true_type) { |
|
|
|
|
Arena* element_arena = TypeHandler::GetArena(value); |
|
|
|
|
Arena* arena = GetArena(); |
|
|
|
|
Arena* element_arena = TypeHandler::GetOwningArena(value); |
|
|
|
|
Arena* arena = GetOwningArena(); |
|
|
|
|
if (arena == element_arena && allocated_size() < total_size_) { |
|
|
|
|
// Fast path: underlying arena representation (tagged pointer) is equal to
|
|
|
|
|
// our arena pointer, and we can add to array without resizing it (at
|
|
|
|
@ -592,7 +594,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { |
|
|
|
|
// First, release an element.
|
|
|
|
|
Value<TypeHandler>* result = UnsafeArenaReleaseLast<TypeHandler>(); |
|
|
|
|
// Now perform a copy if we're on an arena.
|
|
|
|
|
Arena* arena = GetArena(); |
|
|
|
|
Arena* arena = GetOwningArena(); |
|
|
|
|
|
|
|
|
|
#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE |
|
|
|
|
auto* new_result = copy<TypeHandler>(result); |
|
|
|
@ -609,7 +611,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { |
|
|
|
|
// this is the same as UnsafeArenaReleaseLast(). Note that we
|
|
|
|
|
// ABSL_DCHECK-fail if we're on an arena, since the user really should
|
|
|
|
|
// implement the copy operation in this case.
|
|
|
|
|
ABSL_DCHECK(GetArena() == nullptr) |
|
|
|
|
ABSL_DCHECK(GetOwningArena() == nullptr) |
|
|
|
|
<< "ReleaseLast() called on a RepeatedPtrField that is on an arena, " |
|
|
|
|
<< "with a type that does not implement MergeFrom. This is unsafe; " |
|
|
|
|
<< "please implement MergeFrom for your type."; |
|
|
|
@ -619,15 +621,16 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { |
|
|
|
|
template <typename TypeHandler> |
|
|
|
|
PROTOBUF_NOINLINE void SwapFallback(RepeatedPtrFieldBase* other) { |
|
|
|
|
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP |
|
|
|
|
ABSL_DCHECK(GetArena() == nullptr || other->GetArena() != GetArena()); |
|
|
|
|
ABSL_DCHECK(GetOwningArena() == nullptr || |
|
|
|
|
other->GetOwningArena() != GetOwningArena()); |
|
|
|
|
#else // PROTOBUF_FORCE_COPY_IN_SWAP
|
|
|
|
|
ABSL_DCHECK(other->GetArena() != GetArena()); |
|
|
|
|
ABSL_DCHECK(other->GetOwningArena() != GetOwningArena()); |
|
|
|
|
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
|
|
|
|
|
|
|
|
|
|
// Copy semantics in this case. We try to improve efficiency by placing the
|
|
|
|
|
// temporary on |other|'s arena so that messages are copied twice rather
|
|
|
|
|
// than three times.
|
|
|
|
|
RepeatedPtrFieldBase temp(other->GetArena()); |
|
|
|
|
RepeatedPtrFieldBase temp(other->GetOwningArena()); |
|
|
|
|
if (!this->empty()) { |
|
|
|
|
temp.MergeFrom<typename TypeHandler::Type>(*this); |
|
|
|
|
} |
|
|
|
@ -637,7 +640,9 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Gets the Arena on which this RepeatedPtrField stores its elements.
|
|
|
|
|
inline Arena* GetArena() const { return arena_; } |
|
|
|
|
inline Arena* GetArena() const { return GetOwningArena(); } |
|
|
|
|
|
|
|
|
|
inline Arena* GetOwningArena() const { return arena_; } |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
using InternalArenaConstructable_ = void; |
|
|
|
@ -880,8 +885,8 @@ class GenericTypeHandler { |
|
|
|
|
delete value; |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
static inline Arena* GetArena(GenericType* value) { |
|
|
|
|
return Arena::InternalGetArena(value); |
|
|
|
|
static inline Arena* GetOwningArena(GenericType* value) { |
|
|
|
|
return Arena::InternalGetOwningArena(value); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline void Clear(GenericType* value) { value->Clear(); } |
|
|
|
@ -903,8 +908,9 @@ inline MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype( |
|
|
|
|
return NewFromPrototypeHelper(prototype, arena); |
|
|
|
|
} |
|
|
|
|
template <> |
|
|
|
|
inline Arena* GenericTypeHandler<MessageLite>::GetArena(MessageLite* value) { |
|
|
|
|
return value->GetArena(); |
|
|
|
|
inline Arena* GenericTypeHandler<MessageLite>::GetOwningArena( |
|
|
|
|
MessageLite* value) { |
|
|
|
|
return value->GetOwningArena(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename GenericType> |
|
|
|
@ -931,7 +937,8 @@ template <> |
|
|
|
|
PROTOBUF_EXPORT Message* GenericTypeHandler<Message>::NewFromPrototype( |
|
|
|
|
const Message* prototype, Arena* arena); |
|
|
|
|
template <> |
|
|
|
|
PROTOBUF_EXPORT Arena* GenericTypeHandler<Message>::GetArena(Message* value); |
|
|
|
|
PROTOBUF_EXPORT Arena* GenericTypeHandler<Message>::GetOwningArena( |
|
|
|
|
Message* value); |
|
|
|
|
|
|
|
|
|
class StringTypeHandler { |
|
|
|
|
public: |
|
|
|
@ -948,7 +955,7 @@ class StringTypeHandler { |
|
|
|
|
Arena* arena) { |
|
|
|
|
return New(arena); |
|
|
|
|
} |
|
|
|
|
static inline Arena* GetArena(std::string*) { return nullptr; } |
|
|
|
|
static inline Arena* GetOwningArena(std::string*) { return nullptr; } |
|
|
|
|
static inline void Delete(std::string* value, Arena* arena) { |
|
|
|
|
if (arena == nullptr) { |
|
|
|
|
delete value; |
|
|
|
@ -1300,6 +1307,9 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase { |
|
|
|
|
|
|
|
|
|
RepeatedPtrField(Arena* arena, const RepeatedPtrField& rhs); |
|
|
|
|
|
|
|
|
|
// Internal version of GetArena().
|
|
|
|
|
inline Arena* GetOwningArena() const; |
|
|
|
|
|
|
|
|
|
// Implementations for ExtractSubrange(). The copying behavior must be
|
|
|
|
|
// included only if the type supports the necessary operations (e.g.,
|
|
|
|
|
// MergeFrom()), so we must resolve this at compile time. ExtractSubrange()
|
|
|
|
@ -1384,7 +1394,7 @@ inline RepeatedPtrField<Element>::RepeatedPtrField( |
|
|
|
|
// We don't just call Swap(&other) here because it would perform 3 copies if
|
|
|
|
|
// other is on an arena. This field can't be on an arena because arena
|
|
|
|
|
// construction always uses the Arena* accepting constructor.
|
|
|
|
|
if (other.GetArena()) { |
|
|
|
|
if (other.GetOwningArena()) { |
|
|
|
|
CopyFrom(other); |
|
|
|
|
} else { |
|
|
|
|
InternalSwap(&other); |
|
|
|
@ -1398,9 +1408,9 @@ inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=( |
|
|
|
|
// We don't just call Swap(&other) here because it would perform 3 copies if
|
|
|
|
|
// the two fields are on different arenas.
|
|
|
|
|
if (this != &other) { |
|
|
|
|
if (GetArena() != other.GetArena() |
|
|
|
|
if (GetOwningArena() != other.GetOwningArena() |
|
|
|
|
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE |
|
|
|
|
|| GetArena() == nullptr |
|
|
|
|
|| GetOwningArena() == nullptr |
|
|
|
|
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
|
|
|
|
|
) { |
|
|
|
|
CopyFrom(other); |
|
|
|
@ -1482,7 +1492,7 @@ inline void RepeatedPtrField<Element>::DeleteSubrange(int start, int num) { |
|
|
|
|
ABSL_DCHECK_GE(num, 0); |
|
|
|
|
ABSL_DCHECK_LE(start + num, size()); |
|
|
|
|
void** subrange = raw_mutable_data() + start; |
|
|
|
|
Arena* arena = GetArena(); |
|
|
|
|
Arena* arena = GetOwningArena(); |
|
|
|
|
for (int i = 0; i < num; ++i) { |
|
|
|
|
using H = CommonHandler<TypeHandler>; |
|
|
|
|
H::Delete(static_cast<Element*>(subrange[i]), arena); |
|
|
|
@ -1513,7 +1523,7 @@ inline void RepeatedPtrField<Element>::ExtractSubrangeInternal( |
|
|
|
|
<< "Releasing elements without transferring ownership is an unsafe " |
|
|
|
|
"operation. Use UnsafeArenaExtractSubrange."; |
|
|
|
|
if (elements != nullptr) { |
|
|
|
|
Arena* arena = GetArena(); |
|
|
|
|
Arena* arena = GetOwningArena(); |
|
|
|
|
auto* extracted = data() + start; |
|
|
|
|
#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE |
|
|
|
|
// Always copy.
|
|
|
|
@ -1549,7 +1559,7 @@ inline void RepeatedPtrField<Element>::ExtractSubrangeInternal( |
|
|
|
|
// ExtractSubrange() must return heap-allocated objects by contract, and we
|
|
|
|
|
// cannot fulfill this contract if we are an on arena, we must ABSL_DCHECK()
|
|
|
|
|
// that we are not on an arena.
|
|
|
|
|
ABSL_DCHECK(GetArena() == nullptr) |
|
|
|
|
ABSL_DCHECK(GetOwningArena() == nullptr) |
|
|
|
|
<< "ExtractSubrange() when arena is non-nullptr is only supported when " |
|
|
|
|
<< "the Element type supplies a MergeFrom() operation to make copies."; |
|
|
|
|
UnsafeArenaExtractSubrange(start, num, elements); |
|
|
|
@ -1634,7 +1644,7 @@ template <typename Element> |
|
|
|
|
inline void RepeatedPtrField<Element>::UnsafeArenaSwap( |
|
|
|
|
RepeatedPtrField* other) { |
|
|
|
|
if (this == other) return; |
|
|
|
|
ABSL_DCHECK_EQ(GetArena(), other->GetArena()); |
|
|
|
|
ABSL_DCHECK_EQ(GetOwningArena(), other->GetOwningArena()); |
|
|
|
|
RepeatedPtrFieldBase::InternalSwap(other); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1655,6 +1665,11 @@ inline Arena* RepeatedPtrField<Element>::GetArena() const { |
|
|
|
|
} |
|
|
|
|
#endif // !PROTOBUF_FUTURE_REMOVE_CONST_REPEATEDFIELD_GETARENA_API
|
|
|
|
|
|
|
|
|
|
template <typename Element> |
|
|
|
|
inline Arena* RepeatedPtrField<Element>::GetOwningArena() const { |
|
|
|
|
return RepeatedPtrFieldBase::GetOwningArena(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename Element> |
|
|
|
|
inline size_t RepeatedPtrField<Element>::SpaceUsedExcludingSelfLong() const { |
|
|
|
|
// `google::protobuf::Message` has a virtual method `SpaceUsedLong`, hence we can
|
|
|
|
|