aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/generated_message_util.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/generated_message_util.h')
-rw-r--r--src/google/protobuf/generated_message_util.h101
1 files changed, 78 insertions, 23 deletions
diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h
index 8ebfc13b..4da04cae 100644
--- a/src/google/protobuf/generated_message_util.h
+++ b/src/google/protobuf/generated_message_util.h
@@ -39,14 +39,16 @@
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
#include <assert.h>
+#include <atomic>
#include <climits>
#include <string>
#include <vector>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/stubs/once.h> // Add direct dep on port for pb.cc
#include <google/protobuf/has_bits.h>
+#include <google/protobuf/implicit_weak_message.h>
#include <google/protobuf/map_entry_lite.h>
#include <google/protobuf/message_lite.h>
#include <google/protobuf/wire_format_lite.h>
@@ -120,6 +122,21 @@ template <class Type> bool AllAreInitialized(const Type& t) {
return true;
}
+// "Weak" variant of AllAreInitialized, used to implement implicit weak fields.
+// This version operates on MessageLite to avoid introducing a dependency on the
+// concrete message type.
+template <class T>
+bool AllAreInitializedWeak(const ::google::protobuf::RepeatedPtrField<T>& t) {
+ for (int i = t.size(); --i >= 0;) {
+ if (!reinterpret_cast<const ::google::protobuf::internal::RepeatedPtrFieldBase&>(t)
+ .Get<::google::protobuf::internal::ImplicitWeakTypeHandler<T> >(i)
+ .IsInitialized()) {
+ return false;
+ }
+ }
+ return true;
+}
+
LIBPROTOBUF_EXPORT void InitProtobufDefaults();
struct LIBPROTOBUF_EXPORT FieldMetadata {
@@ -148,7 +165,8 @@ struct LIBPROTOBUF_EXPORT FieldMetadata {
enum {
kCordType = 19,
kStringPieceType = 20,
- kNumTypes = 20,
+ kInlinedType = 21,
+ kNumTypes = 21,
kSpecial = kNumTypes * kNumTypeClasses,
};
@@ -157,7 +175,7 @@ struct LIBPROTOBUF_EXPORT FieldMetadata {
inline bool IsPresent(const void* base, uint32 hasbit) {
const uint32* has_bits_array = static_cast<const uint32*>(base);
- return has_bits_array[hasbit / 32] & (1u << (hasbit & 31));
+ return (has_bits_array[hasbit / 32] & (1u << (hasbit & 31))) != 0;
}
inline bool IsOneofPresent(const void* base, uint32 offset, uint32 tag) {
@@ -183,7 +201,7 @@ struct SerializationTable {
};
LIBPROTOBUF_EXPORT void SerializeInternal(const uint8* base, const FieldMetadata* table,
- int num_fields, ::google::protobuf::io::CodedOutputStream* output);
+ int32 num_fields, ::google::protobuf::io::CodedOutputStream* output);
inline void TableSerialize(const ::google::protobuf::MessageLite& msg,
const SerializationTable* table,
@@ -201,7 +219,7 @@ inline void TableSerialize(const ::google::protobuf::MessageLite& msg,
}
uint8* SerializeInternalToArray(const uint8* base, const FieldMetadata* table,
- int num_fields, bool is_deterministic,
+ int32 num_fields, bool is_deterministic,
uint8* buffer);
inline uint8* TableSerializeToArray(const ::google::protobuf::MessageLite& msg,
@@ -274,17 +292,17 @@ void MapFieldSerializer(const uint8* base, uint32 offset, uint32 tag,
}
}
-LIBPROTOBUF_EXPORT MessageLite* DuplicateIfNonNullInternal(MessageLite* message, Arena* arena);
+LIBPROTOBUF_EXPORT MessageLite* DuplicateIfNonNullInternal(MessageLite* message);
LIBPROTOBUF_EXPORT MessageLite* GetOwnedMessageInternal(Arena* message_arena,
MessageLite* submessage,
Arena* submessage_arena);
template <typename T>
-T* DuplicateIfNonNull(T* message, Arena* arena) {
+T* DuplicateIfNonNull(T* message) {
// The casts must be reinterpret_cast<> because T might be a forward-declared
// type that the compiler doesn't know is related to MessageLite.
- return reinterpret_cast<T*>(DuplicateIfNonNullInternal(
- reinterpret_cast<MessageLite*>(message), arena));
+ return reinterpret_cast<T*>(
+ DuplicateIfNonNullInternal(reinterpret_cast<MessageLite*>(message)));
}
template <typename T>
@@ -297,20 +315,57 @@ T* GetOwnedMessage(Arena* message_arena, T* submessage,
submessage_arena));
}
-// Returns a message owned by this Arena. This may require Own()ing or
-// duplicating the message.
-template <typename T>
-T* GetOwnedMessage(T* message, Arena* arena) {
- GOOGLE_DCHECK(message);
- Arena* message_arena = google::protobuf::Arena::GetArena(message);
- if (message_arena == arena) {
- return message;
- } else if (arena != NULL && message_arena == NULL) {
- arena->Own(message);
- return message;
- } else {
- return DuplicateIfNonNull(message, arena);
- }
+// Hide atomic from the public header and allow easy change to regular int
+// on platforms where the atomic might have a perf impact.
+class LIBPROTOBUF_EXPORT CachedSize {
+ public:
+ int Get() const { return size_.load(std::memory_order_relaxed); }
+ void Set(int size) { size_.store(size, std::memory_order_relaxed); }
+ private:
+ std::atomic<int> size_{0};
+};
+
+// SCCInfo represents information of a strongly connected component of
+// mutual dependent messages.
+struct LIBPROTOBUF_EXPORT SCCInfoBase {
+ // We use 0 for the Initialized state, because test eax,eax, jnz is smaller
+ // and is subject to macro fusion.
+ enum {
+ kInitialized = 0, // final state
+ kRunning = 1,
+ kUninitialized = -1, // initial state
+ };
+#ifndef _MSC_VER
+ std::atomic<int> visit_status;
+#else
+ // MSVC doesnt make std::atomic constant initialized. This union trick
+ // makes it so.
+ union {
+ int visit_status_to_make_linker_init;
+ std::atomic<int> visit_status;
+ };
+#endif
+ int num_deps;
+ void (*init_func)();
+ // This is followed by an array of num_deps
+ // const SCCInfoBase* deps[];
+};
+
+template <int N>
+struct SCCInfo {
+ SCCInfoBase base;
+ // Semantically this is const SCCInfo<T>* which is is a templated type.
+ // The obvious inheriting from SCCInfoBase mucks with struct initialization.
+ // Attempts showed the compiler was generating dynamic initialization code.
+ // Zero length arrays produce warnings with MSVC.
+ SCCInfoBase* deps[N ? N : 1];
+};
+
+LIBPROTOBUF_EXPORT void InitSCCImpl(SCCInfoBase* scc);
+
+inline void InitSCC(SCCInfoBase* scc) {
+ auto status = scc->visit_status.load(std::memory_order_acquire);
+ if (GOOGLE_PREDICT_FALSE(status != SCCInfoBase::kInitialized)) InitSCCImpl(scc);
}
} // namespace internal