diff options
author | Adam Cozzette <acozzette@google.com> | 2018-03-13 16:37:29 -0700 |
---|---|---|
committer | Adam Cozzette <acozzette@google.com> | 2018-03-13 16:37:29 -0700 |
commit | 0400cca3236de1ca303af38bf81eab332d042b7c (patch) | |
tree | a8a9b19853f64567c96750a1c7d253926471daa5 /src/google/protobuf/generated_message_util.cc | |
parent | 96b535cc2f4f7b7e22a1b8622149f7c26a5a3f63 (diff) | |
download | protobuf-0400cca3236de1ca303af38bf81eab332d042b7c.tar.gz protobuf-0400cca3236de1ca303af38bf81eab332d042b7c.tar.bz2 protobuf-0400cca3236de1ca303af38bf81eab332d042b7c.zip |
Integrated internal changes from Google
Diffstat (limited to 'src/google/protobuf/generated_message_util.cc')
-rw-r--r-- | src/google/protobuf/generated_message_util.cc | 91 |
1 files changed, 87 insertions, 4 deletions
diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc index 15d84222..dac8ca90 100644 --- a/src/google/protobuf/generated_message_util.cc +++ b/src/google/protobuf/generated_message_util.cc @@ -35,6 +35,9 @@ #include <google/protobuf/generated_message_util.h> #include <limits> +// We're only using this as a standard way for getting the thread id. +// We're not using any thread functionality. +#include <thread> // NOLINT #include <vector> #include <google/protobuf/io/coded_stream_inl.h> @@ -43,6 +46,7 @@ #include <google/protobuf/extension_set.h> #include <google/protobuf/message_lite.h> #include <google/protobuf/metadata_lite.h> +#include <google/protobuf/stubs/mutex.h> #include <google/protobuf/stubs/port.h> #include <google/protobuf/repeated_field.h> #include <google/protobuf/wire_format_lite.h> @@ -61,7 +65,7 @@ double NaN() { return std::numeric_limits<double>::quiet_NaN(); } -ExplicitlyConstructed< ::std::string> fixed_address_empty_string; +ExplicitlyConstructed<::std::string> fixed_address_empty_string; GOOGLE_PROTOBUF_DECLARE_ONCE(empty_string_once_init_); void DeleteEmptyString() { fixed_address_empty_string.Destruct(); } @@ -251,6 +255,10 @@ struct PrimitiveTypeHelper<WireFormatLite::TYPE_BYTES> : PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {}; +template <> +struct PrimitiveTypeHelper<FieldMetadata::kInlinedType> + : PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {}; + // We want to serialize to both CodedOutputStream and directly into byte arrays // without duplicating the code. In fact we might want extra output channels in // the future. @@ -274,7 +282,7 @@ void WriteLengthTo(uint32 length, O* output) { // Specialization for coded output stream template <int type> -struct OutputHelper< ::google::protobuf::io::CodedOutputStream, type> { +struct OutputHelper<::google::protobuf::io::CodedOutputStream, type> { static void Serialize(const void* ptr, ::google::protobuf::io::CodedOutputStream* output) { PrimitiveTypeHelper<type>::Serialize(ptr, output); @@ -416,6 +424,15 @@ struct SingularFieldHelper<WireFormatLite::TYPE_MESSAGE> { } }; +template <> +struct SingularFieldHelper<FieldMetadata::kInlinedType> { + template <typename O> + static void Serialize(const void* field, const FieldMetadata& md, O* output) { + WriteTagTo(md.tag, output); + SerializeTo<FieldMetadata::kInlinedType>(&Get<::std::string>(field), output); + } +}; + template <int type> struct RepeatedFieldHelper { template <typename O> @@ -488,6 +505,10 @@ struct RepeatedFieldHelper<WireFormatLite::TYPE_MESSAGE> { }; +template <> +struct RepeatedFieldHelper<FieldMetadata::kInlinedType> + : RepeatedFieldHelper<WireFormatLite::TYPE_STRING> {}; + template <int type> struct PackedFieldHelper { template <typename O> @@ -523,6 +544,9 @@ struct PackedFieldHelper<WireFormatLite::TYPE_GROUP> template <> struct PackedFieldHelper<WireFormatLite::TYPE_MESSAGE> : PackedFieldHelper<WireFormatLite::TYPE_STRING> {}; +template <> +struct PackedFieldHelper<FieldMetadata::kInlinedType> + : PackedFieldHelper<WireFormatLite::TYPE_STRING> {}; template <int type> struct OneOfFieldHelper { @@ -533,6 +557,15 @@ struct OneOfFieldHelper { }; +template <> +struct OneOfFieldHelper<FieldMetadata::kInlinedType> { + template <typename O> + static void Serialize(const void* field, const FieldMetadata& md, O* output) { + SingularFieldHelper<FieldMetadata::kInlinedType>::Serialize( + Get<const ::std::string*>(field), md, output); + } +}; + void SerializeNotImplemented(int field) { GOOGLE_LOG(FATAL) << "Not implemented field number " << field; } @@ -573,6 +606,11 @@ bool IsNull<WireFormatLite::TYPE_MESSAGE>(const void* ptr) { } +template <> +bool IsNull<FieldMetadata::kInlinedType>(const void* ptr) { + return static_cast<const ::std::string*>(ptr)->empty(); +} + #define SERIALIZERS_FOR_TYPE(type) \ case SERIALIZE_TABLE_OP(type, FieldMetadata::kPresence): \ if (!IsPresent(base, field_metadata.has_offset)) continue; \ @@ -620,6 +658,7 @@ void SerializeInternal(const uint8* base, SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64); + SERIALIZERS_FOR_TYPE(FieldMetadata::kInlinedType); // Special cases case FieldMetadata::kSpecial: @@ -663,6 +702,7 @@ uint8* SerializeInternalToArray(const uint8* base, SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64); + SERIALIZERS_FOR_TYPE(FieldMetadata::kInlinedType); // Special cases case FieldMetadata::kSpecial: { io::ArrayOutputStream array_stream(array_output.ptr, INT_MAX); @@ -698,9 +738,9 @@ void UnknownFieldSerializerLite(const uint8* ptr, uint32 offset, uint32 tag, ->unknown_fields()); } -MessageLite* DuplicateIfNonNullInternal(MessageLite* message, Arena* arena) { +MessageLite* DuplicateIfNonNullInternal(MessageLite* message) { if (message) { - MessageLite* ret = message->New(arena); + MessageLite* ret = message->New(); ret->CheckTypeAndMergeFrom(*message); return ret; } else { @@ -725,6 +765,49 @@ MessageLite* GetOwnedMessageInternal(Arena* message_arena, } } +namespace { + +void InitSCC_DFS(SCCInfoBase* scc) { + if (scc->visit_status.load(std::memory_order_relaxed) != + SCCInfoBase::kUninitialized) return; + scc->visit_status.store(SCCInfoBase::kRunning, std::memory_order_relaxed); + // Each base is followed by an array of pointers to deps + auto deps = reinterpret_cast<SCCInfoBase* const*>(scc + 1); + for (int i = 0; i < scc->num_deps; i++) { + if (deps[i]) InitSCC_DFS(deps[i]); + } + scc->init_func(); + // Mark done (note we use memory order release here), other threads could + // now see this as initialized and thus the initialization must have happened + // before. + scc->visit_status.store(SCCInfoBase::kInitialized, std::memory_order_release); +} + +} // namespace + +void InitSCCImpl(SCCInfoBase* scc) { + static WrappedMutex mu{GOOGLE_PROTOBUF_LINKER_INITIALIZED}; + // Either the default in case no initialization is running or the id of the + // thread that is currently initializing. + static std::atomic<std::thread::id> runner; + auto me = std::this_thread::get_id(); + // This will only happen because the constructor will call InitSCC while + // constructing the default instance. + if (runner.load(std::memory_order_relaxed) == me) { + // Because we're in the process of constructing the default instance. + // We can be assured that we're already exploring this SCC. + GOOGLE_CHECK_EQ(scc->visit_status.load(std::memory_order_relaxed), + SCCInfoBase::kRunning); + return; + } + InitProtobufDefaults(); + mu.Lock(); + runner.store(me, std::memory_order_relaxed); + InitSCC_DFS(scc); + runner.store(std::thread::id{}, std::memory_order_relaxed); + mu.Unlock(); +} + } // namespace internal } // namespace protobuf } // namespace google |