Browse Source

Merge pull request #4882 from google/3.6.x

Merge 3.6.x into master
Adam Cozzette 7 years ago
parent
commit
4129b6aaad

+ 27 - 70
src/google/protobuf/descriptor.cc

@@ -479,15 +479,8 @@ typedef std::map<DescriptorIntPair, const FieldDescriptor*>
   ExtensionsGroupedByDescriptorMap;
 typedef HASH_MAP<string, const SourceCodeInfo_Location*> LocationsByPathMap;
 
-std::set<string>* allowed_proto3_extendees_ = NULL;
-GOOGLE_PROTOBUF_DECLARE_ONCE(allowed_proto3_extendees_init_);
-
-void DeleteAllowedProto3Extendee() {
-  delete allowed_proto3_extendees_;
-}
-
-void InitAllowedProto3Extendee() {
-  allowed_proto3_extendees_ = new std::set<string>;
+std::set<string>* NewAllowedProto3Extendee() {
+  auto allowed_proto3_extendees = new std::set<string>;
   const char* kOptionNames[] = {
       "FileOptions",      "MessageOptions", "FieldOptions", "EnumOptions",
       "EnumValueOptions", "ServiceOptions", "MethodOptions", "OneofOptions"};
@@ -495,14 +488,13 @@ void InitAllowedProto3Extendee() {
     // descriptor.proto has a different package name in opensource. We allow
     // both so the opensource protocol compiler can also compile internal
     // proto3 files with custom options. See: b/27567912
-    allowed_proto3_extendees_->insert(string("google.protobuf.") +
+    allowed_proto3_extendees->insert(string("google.protobuf.") +
                                       kOptionNames[i]);
     // Split the word to trick the opensource processing scripts so they
     // will keep the origial package name.
-    allowed_proto3_extendees_->insert(string("proto") + "2." + kOptionNames[i]);
+    allowed_proto3_extendees->insert(string("proto") + "2." + kOptionNames[i]);
   }
-
-  google::protobuf::internal::OnShutdown(&DeleteAllowedProto3Extendee);
+  return allowed_proto3_extendees;
 }
 
 // Checks whether the extendee type is allowed in proto3.
@@ -510,9 +502,10 @@ void InitAllowedProto3Extendee() {
 // instead of comparing the descriptor directly because the extensions may be
 // defined in a different pool.
 bool AllowedExtendeeInProto3(const string& name) {
-  ::google::protobuf::GoogleOnceInit(&allowed_proto3_extendees_init_, &InitAllowedProto3Extendee);
-  return allowed_proto3_extendees_->find(name) !=
-         allowed_proto3_extendees_->end();
+  static auto allowed_proto3_extendees =
+      internal::OnShutdownDelete(NewAllowedProto3Extendee());
+  return allowed_proto3_extendees->find(name) !=
+         allowed_proto3_extendees->end();
 }
 
 }  // anonymous namespace
@@ -829,31 +822,10 @@ FileDescriptorTables::FileDescriptorTables()
 
 FileDescriptorTables::~FileDescriptorTables() {}
 
-namespace {
-
-FileDescriptorTables* file_descriptor_tables_ = NULL;
-GOOGLE_PROTOBUF_DECLARE_ONCE(file_descriptor_tables_once_init_);
-
-void DeleteFileDescriptorTables() {
-  delete file_descriptor_tables_;
-  file_descriptor_tables_ = NULL;
-}
-
-void InitFileDescriptorTables() {
-  file_descriptor_tables_ = new FileDescriptorTables();
-  internal::OnShutdown(&DeleteFileDescriptorTables);
-}
-
-inline void InitFileDescriptorTablesOnce() {
-  ::google::protobuf::GoogleOnceInit(
-      &file_descriptor_tables_once_init_, &InitFileDescriptorTables);
-}
-
-}  // anonymous namespace
-
 inline const FileDescriptorTables& FileDescriptorTables::GetEmptyInstance() {
-  InitFileDescriptorTablesOnce();
-  return *file_descriptor_tables_;
+  static auto file_descriptor_tables =
+      internal::OnShutdownDelete(new FileDescriptorTables());
+  return *file_descriptor_tables;
 }
 
 void DescriptorPool::Tables::AddCheckpoint() {
@@ -1335,42 +1307,28 @@ bool DescriptorPool::InternalIsFileLoaded(const string& filename) const {
 
 namespace {
 
-
-EncodedDescriptorDatabase* generated_database_ = NULL;
-DescriptorPool* generated_pool_ = NULL;
-GOOGLE_PROTOBUF_DECLARE_ONCE(generated_pool_init_);
-
-void DeleteGeneratedPool() {
-  delete generated_database_;
-  generated_database_ = NULL;
-  delete generated_pool_;
-  generated_pool_ = NULL;
-}
-
-static void InitGeneratedPool() {
-  generated_database_ = new EncodedDescriptorDatabase;
-  generated_pool_ = new DescriptorPool(generated_database_);
-  generated_pool_->InternalSetLazilyBuildDependencies();
-
-  internal::OnShutdown(&DeleteGeneratedPool);
+EncodedDescriptorDatabase* GeneratedDatabase() {
+  static auto generated_database =
+      internal::OnShutdownDelete(new EncodedDescriptorDatabase());
+  return generated_database;
 }
 
-inline void InitGeneratedPoolOnce() {
-  ::google::protobuf::GoogleOnceInit(&generated_pool_init_, &InitGeneratedPool);
+DescriptorPool* NewGeneratedPool() {
+  auto generated_pool = new DescriptorPool(GeneratedDatabase());
+  generated_pool->InternalSetLazilyBuildDependencies();
+  return generated_pool;
 }
 
 }  // anonymous namespace
 
-const DescriptorPool* DescriptorPool::generated_pool() {
-  InitGeneratedPoolOnce();
-  return generated_pool_;
+DescriptorPool* DescriptorPool::internal_generated_pool() {
+  static DescriptorPool* generated_pool =
+      internal::OnShutdownDelete(NewGeneratedPool());
+  return generated_pool;
 }
 
-
-
-DescriptorPool* DescriptorPool::internal_generated_pool() {
-  InitGeneratedPoolOnce();
-  return generated_pool_;
+const DescriptorPool* DescriptorPool::generated_pool() {
+  return internal_generated_pool();
 }
 
 void DescriptorPool::InternalAddGeneratedFile(
@@ -1397,8 +1355,7 @@ void DescriptorPool::InternalAddGeneratedFile(
   // Therefore, when we parse one, we have to be very careful to avoid using
   // any descriptor-based operations, since this might cause infinite recursion
   // or deadlock.
-  InitGeneratedPoolOnce();
-  GOOGLE_CHECK(generated_database_->Add(encoded_file_descriptor, size));
+  GOOGLE_CHECK(GeneratedDatabase()->Add(encoded_file_descriptor, size));
 }
 
 

+ 15 - 77
src/google/protobuf/extension_set.cc

@@ -36,7 +36,6 @@
 #include <tuple>
 #include <utility>
 #include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/once.h>
 #include <google/protobuf/extension_set.h>
 #include <google/protobuf/message_lite.h>
 #include <google/protobuf/io/coded_stream.h>
@@ -80,27 +79,17 @@ inline bool is_packable(WireFormatLite::WireType type) {
 // Registry stuff.
 typedef hash_map<std::pair<const MessageLite*, int>,
                  ExtensionInfo> ExtensionRegistry;
-ExtensionRegistry* registry_ = NULL;
-GOOGLE_PROTOBUF_DECLARE_ONCE(registry_init_);
 
-void DeleteRegistry() {
-  delete registry_;
-  registry_ = NULL;
-}
-
-void InitRegistry() {
-  registry_ = new ExtensionRegistry;
-  OnShutdown(&DeleteRegistry);
-}
+static const ExtensionRegistry* global_registry = nullptr;
 
 // This function is only called at startup, so there is no need for thread-
 // safety.
 void Register(const MessageLite* containing_type,
               int number, ExtensionInfo info) {
-  ::google::protobuf::GoogleOnceInit(&registry_init_, &InitRegistry);
-
-  if (!InsertIfNotPresent(registry_, std::make_pair(containing_type, number),
-                          info)) {
+  static auto local_static_registry = OnShutdownDelete(new ExtensionRegistry);
+  global_registry = local_static_registry;
+  if (!InsertIfNotPresent(local_static_registry,
+                          std::make_pair(containing_type, number), info)) {
     GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \""
                << containing_type->GetTypeName()
                << "\", field number " << number << ".";
@@ -109,9 +98,9 @@ void Register(const MessageLite* containing_type,
 
 const ExtensionInfo* FindRegisteredExtension(
     const MessageLite* containing_type, int number) {
-  return (registry_ == NULL)
-             ? NULL
-             : FindOrNull(*registry_, std::make_pair(containing_type, number));
+  return global_registry == nullptr
+      ? nullptr
+      : FindOrNull(*global_registry, std::make_pair(containing_type, number));
 }
 
 }  // namespace
@@ -1911,67 +1900,16 @@ void ExtensionSet::Erase(int key) {
 // ==================================================================
 // Default repeated field instances for iterator-compatible accessors
 
-GOOGLE_PROTOBUF_DECLARE_ONCE(repeated_primitive_generic_type_traits_once_init_);
-GOOGLE_PROTOBUF_DECLARE_ONCE(repeated_string_type_traits_once_init_);
-GOOGLE_PROTOBUF_DECLARE_ONCE(repeated_message_generic_type_traits_once_init_);
-
-void RepeatedPrimitiveGenericTypeTraits::InitializeDefaultRepeatedFields() {
-  default_repeated_field_int32_ = new RepeatedField<int32>;
-  default_repeated_field_int64_ = new RepeatedField<int64>;
-  default_repeated_field_uint32_ = new RepeatedField<uint32>;
-  default_repeated_field_uint64_ = new RepeatedField<uint64>;
-  default_repeated_field_double_ = new RepeatedField<double>;
-  default_repeated_field_float_ = new RepeatedField<float>;
-  default_repeated_field_bool_ = new RepeatedField<bool>;
-  OnShutdown(&DestroyDefaultRepeatedFields);
-}
-
-void RepeatedPrimitiveGenericTypeTraits::DestroyDefaultRepeatedFields() {
-  delete default_repeated_field_int32_;
-  delete default_repeated_field_int64_;
-  delete default_repeated_field_uint32_;
-  delete default_repeated_field_uint64_;
-  delete default_repeated_field_double_;
-  delete default_repeated_field_float_;
-  delete default_repeated_field_bool_;
-}
-
-void RepeatedStringTypeTraits::InitializeDefaultRepeatedFields() {
-  default_repeated_field_ = new RepeatedFieldType;
-  OnShutdown(&DestroyDefaultRepeatedFields);
-}
-
-void RepeatedStringTypeTraits::DestroyDefaultRepeatedFields() {
-  delete default_repeated_field_;
-}
-
-void RepeatedMessageGenericTypeTraits::InitializeDefaultRepeatedFields() {
-  default_repeated_field_ = new RepeatedFieldType;
-  OnShutdown(&DestroyDefaultRepeatedFields);
-}
-
-void RepeatedMessageGenericTypeTraits::DestroyDefaultRepeatedFields() {
-  delete default_repeated_field_;
+const RepeatedPrimitiveDefaults* RepeatedPrimitiveDefaults::default_instance() {
+  static auto instance = OnShutdownDelete(new RepeatedPrimitiveDefaults);
+  return instance;
 }
 
-const RepeatedField<int32>*
-RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int32_ = NULL;
-const RepeatedField<int64>*
-RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int64_ = NULL;
-const RepeatedField<uint32>*
-RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint32_ = NULL;
-const RepeatedField<uint64>*
-RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint64_ = NULL;
-const RepeatedField<double>*
-RepeatedPrimitiveGenericTypeTraits::default_repeated_field_double_ = NULL;
-const RepeatedField<float>*
-RepeatedPrimitiveGenericTypeTraits::default_repeated_field_float_ = NULL;
-const RepeatedField<bool>*
-RepeatedPrimitiveGenericTypeTraits::default_repeated_field_bool_ = NULL;
 const RepeatedStringTypeTraits::RepeatedFieldType*
-RepeatedStringTypeTraits::default_repeated_field_ = NULL;
-const RepeatedMessageGenericTypeTraits::RepeatedFieldType*
-RepeatedMessageGenericTypeTraits::default_repeated_field_ = NULL;
+RepeatedStringTypeTraits::GetDefaultRepeatedField() {
+  static auto instance = OnShutdownDelete(new RepeatedFieldType);
+  return instance;
+}
 
 }  // namespace internal
 }  // namespace protobuf

+ 14 - 42
src/google/protobuf/extension_set.h

@@ -880,18 +880,17 @@ class RepeatedPrimitiveTypeTraits {
 
 LIBPROTOBUF_EXPORT extern ProtobufOnceType repeated_primitive_generic_type_traits_once_init_;
 
-class LIBPROTOBUF_EXPORT RepeatedPrimitiveGenericTypeTraits {
+class LIBPROTOBUF_EXPORT RepeatedPrimitiveDefaults {
  private:
   template<typename Type> friend class RepeatedPrimitiveTypeTraits;
-  static void InitializeDefaultRepeatedFields();
-  static void DestroyDefaultRepeatedFields();
-  static const RepeatedField<int32>* default_repeated_field_int32_;
-  static const RepeatedField<int64>* default_repeated_field_int64_;
-  static const RepeatedField<uint32>* default_repeated_field_uint32_;
-  static const RepeatedField<uint64>* default_repeated_field_uint64_;
-  static const RepeatedField<double>* default_repeated_field_double_;
-  static const RepeatedField<float>* default_repeated_field_float_;
-  static const RepeatedField<bool>* default_repeated_field_bool_;
+  static const RepeatedPrimitiveDefaults* default_instance();
+  RepeatedField<int32> default_repeated_field_int32_;
+  RepeatedField<int64> default_repeated_field_int64_;
+  RepeatedField<uint32> default_repeated_field_uint32_;
+  RepeatedField<uint64> default_repeated_field_uint64_;
+  RepeatedField<double> default_repeated_field_double_;
+  RepeatedField<float> default_repeated_field_float_;
+  RepeatedField<bool> default_repeated_field_bool_;
 };
 
 #define PROTOBUF_DEFINE_PRIMITIVE_TYPE(TYPE, METHOD)                       \
@@ -919,11 +918,8 @@ template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Add(             \
 }                                                                          \
 template<> inline const RepeatedField<TYPE>*                               \
     RepeatedPrimitiveTypeTraits<TYPE>::GetDefaultRepeatedField() {         \
-  ::google::protobuf::GoogleOnceInit(                                                          \
-      &repeated_primitive_generic_type_traits_once_init_,                  \
-      &RepeatedPrimitiveGenericTypeTraits::InitializeDefaultRepeatedFields); \
-  return RepeatedPrimitiveGenericTypeTraits::                              \
-      default_repeated_field_##TYPE##_;                                    \
+  return &RepeatedPrimitiveDefaults::default_instance()                    \
+              ->default_repeated_field_##TYPE##_;                          \
 }                                                                          \
 template<> inline const RepeatedField<TYPE>&                               \
     RepeatedPrimitiveTypeTraits<TYPE>::GetRepeated(int number,             \
@@ -980,8 +976,6 @@ class LIBPROTOBUF_EXPORT StringTypeTraits {
   }
 };
 
-LIBPROTOBUF_EXPORT extern ProtobufOnceType repeated_string_type_traits_once_init_;
-
 class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
  public:
   typedef const string& ConstType;
@@ -1024,11 +1018,7 @@ class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
                                      is_packed, NULL));
   }
 
-  static const RepeatedFieldType* GetDefaultRepeatedField() {
-    ::google::protobuf::GoogleOnceInit(&repeated_string_type_traits_once_init_,
-                   &InitializeDefaultRepeatedFields);
-    return default_repeated_field_;
-  }
+  static const RepeatedFieldType* GetDefaultRepeatedField();
 
   template <typename ExtendeeT>
   static void Register(int number, FieldType type, bool is_packed) {
@@ -1039,7 +1029,6 @@ class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
  private:
   static void InitializeDefaultRepeatedFields();
   static void DestroyDefaultRepeatedFields();
-  static const RepeatedFieldType *default_repeated_field_;
 };
 
 // -------------------------------------------------------------------
@@ -1230,28 +1219,11 @@ class RepeatedMessageTypeTraits {
   }
 };
 
-LIBPROTOBUF_EXPORT extern ProtobufOnceType repeated_message_generic_type_traits_once_init_;
-
-// This class exists only to hold a generic default empty repeated field for all
-// message-type repeated field extensions.
-class LIBPROTOBUF_EXPORT RepeatedMessageGenericTypeTraits {
- public:
-  typedef RepeatedPtrField<::google::protobuf::MessageLite*> RepeatedFieldType;
- private:
-  template<typename Type> friend class RepeatedMessageTypeTraits;
-  static void InitializeDefaultRepeatedFields();
-  static void DestroyDefaultRepeatedFields();
-  static const RepeatedFieldType* default_repeated_field_;
-};
-
 template<typename Type> inline
     const typename RepeatedMessageTypeTraits<Type>::RepeatedFieldType*
     RepeatedMessageTypeTraits<Type>::GetDefaultRepeatedField() {
-  ::google::protobuf::GoogleOnceInit(
-      &repeated_message_generic_type_traits_once_init_,
-      &RepeatedMessageGenericTypeTraits::InitializeDefaultRepeatedFields);
-  return reinterpret_cast<const RepeatedFieldType*>(
-      RepeatedMessageGenericTypeTraits::default_repeated_field_);
+  static auto instance = OnShutdownDelete(new RepeatedFieldType);
+  return instance;
 }
 
 // -------------------------------------------------------------------

+ 10 - 16
src/google/protobuf/generated_message_reflection.cc

@@ -2327,32 +2327,26 @@ class AssignDescriptorsHelper {
 // automatically delete the allocated reflection. MetadataOwner owns
 // all the allocated reflection instances.
 struct MetadataOwner {
+  ~MetadataOwner() {
+    for (auto range : metadata_arrays_) {
+      for (const Metadata* m = range.first; m < range.second; m++) {
+        delete m->reflection;
+      }
+    }
+  }
+
   void AddArray(const Metadata* begin, const Metadata* end) {
     MutexLock lock(&mu_);
     metadata_arrays_.push_back(std::make_pair(begin, end));
   }
 
   static MetadataOwner* Instance() {
-    static MetadataOwner* res = new MetadataOwner;
+    static MetadataOwner* res = OnShutdownDelete(new MetadataOwner);
     return res;
   }
 
  private:
-  // Use the constructor to register the shutdown code. Because c++ makes sure
-  // this called only once.
-  MetadataOwner() { OnShutdown(&DeleteMetadata); }
-  ~MetadataOwner() {
-    for (int i = 0; i < metadata_arrays_.size(); i++) {
-      for (const Metadata* m = metadata_arrays_[i].first;
-           m < metadata_arrays_[i].second; m++) {
-        delete m->reflection;
-      }
-    }
-  }
-
-  static void DeleteMetadata() {
-    delete Instance();
-  }
+  MetadataOwner() = default;  // private because singleton
 
   Mutex mu_;
   std::vector<std::pair<const Metadata*, const Metadata*> > metadata_arrays_;

+ 14 - 13
src/google/protobuf/generated_message_util.cc

@@ -57,6 +57,12 @@ namespace google {
 namespace protobuf {
 namespace internal {
 
+void DestroyMessage(const void* message) {
+  static_cast<const MessageLite*>(message)->~MessageLite();
+}
+void DestroyString(const void* s) { static_cast<const string*>(s)->~string(); }
+
+ExplicitlyConstructed<std::string> fixed_address_empty_string;
 
 double Infinity() {
   return std::numeric_limits<double>::infinity();
@@ -65,14 +71,15 @@ double NaN() {
   return std::numeric_limits<double>::quiet_NaN();
 }
 
-ExplicitlyConstructed<::std::string> fixed_address_empty_string;
-GOOGLE_PROTOBUF_DECLARE_ONCE(empty_string_once_init_);
-
-void DeleteEmptyString() { fixed_address_empty_string.Destruct(); }
-
-void InitEmptyString() {
+static bool InitProtobufDefaultsImpl() {
   fixed_address_empty_string.DefaultConstruct();
-  OnShutdown(&DeleteEmptyString);
+  OnShutdownDestroyString(fixed_address_empty_string.get_mutable());
+  return true;
+}
+
+void InitProtobufDefaults() {
+  static bool is_inited = InitProtobufDefaultsImpl();
+  (void)is_inited;
 }
 
 size_t StringSpaceUsedExcludingSelfLong(const string& str) {
@@ -86,12 +93,6 @@ size_t StringSpaceUsedExcludingSelfLong(const string& str) {
   }
 }
 
-
-
-void InitProtobufDefaults() {
-  GetEmptyString();
-}
-
 template <typename T>
 const T& Get(const void* ptr) {
   return *static_cast<const T*>(ptr);

+ 18 - 2
src/google/protobuf/generated_message_util.h

@@ -109,6 +109,13 @@ namespace internal {
 LIBPROTOBUF_EXPORT double Infinity();
 LIBPROTOBUF_EXPORT double NaN();
 
+LIBPROTOBUF_EXPORT void InitProtobufDefaults();
+
+// This used by proto1
+inline const std::string& GetEmptyString() {
+  InitProtobufDefaults();
+  return GetEmptyStringAlreadyInited();
+}
 
 // True if IsInitialized() is true for all elements of t.  Type is expected
 // to be a RepeatedPtrField<some message type>.  It's useful to have this
@@ -137,8 +144,6 @@ bool AllAreInitializedWeak(const ::google::protobuf::RepeatedPtrField<T>& t) {
   return true;
 }
 
-LIBPROTOBUF_EXPORT void InitProtobufDefaults();
-
 struct LIBPROTOBUF_EXPORT FieldMetadata {
   uint32 offset;  // offset of this field in the struct
   uint32 tag;     // field * 8 + wire_type
@@ -368,6 +373,17 @@ inline void InitSCC(SCCInfoBase* scc) {
   if (GOOGLE_PREDICT_FALSE(status != SCCInfoBase::kInitialized)) InitSCCImpl(scc);
 }
 
+LIBPROTOBUF_EXPORT void DestroyMessage(const void* message);
+LIBPROTOBUF_EXPORT void DestroyString(const void* s);
+// Destroy (not delete) the message
+inline void OnShutdownDestroyMessage(const void* ptr) {
+  OnShutdownRun(DestroyMessage, ptr);
+}
+// Destroy the string (call string destructor)
+inline void OnShutdownDestroyString(const std::string* ptr) {
+  OnShutdownRun(DestroyString, ptr);
+}
+
 }  // namespace internal
 }  // namespace protobuf
 

+ 2 - 21
src/google/protobuf/message.cc

@@ -262,9 +262,6 @@ namespace {
 
 class GeneratedMessageFactory : public MessageFactory {
  public:
-  GeneratedMessageFactory();
-  ~GeneratedMessageFactory();
-
   static GeneratedMessageFactory* singleton();
 
   typedef void RegistrationFunc(const string&);
@@ -284,25 +281,9 @@ class GeneratedMessageFactory : public MessageFactory {
   hash_map<const Descriptor*, const Message*> type_map_;
 };
 
-GeneratedMessageFactory* generated_message_factory_ = NULL;
-GOOGLE_PROTOBUF_DECLARE_ONCE(generated_message_factory_once_init_);
-
-void ShutdownGeneratedMessageFactory() {
-  delete generated_message_factory_;
-}
-
-void InitGeneratedMessageFactory() {
-  generated_message_factory_ = new GeneratedMessageFactory;
-  internal::OnShutdown(&ShutdownGeneratedMessageFactory);
-}
-
-GeneratedMessageFactory::GeneratedMessageFactory() {}
-GeneratedMessageFactory::~GeneratedMessageFactory() {}
-
 GeneratedMessageFactory* GeneratedMessageFactory::singleton() {
-  ::google::protobuf::GoogleOnceInit(&generated_message_factory_once_init_,
-                 &InitGeneratedMessageFactory);
-  return generated_message_factory_;
+  static auto instance = internal::OnShutdownDelete(new GeneratedMessageFactory);
+  return instance;
 }
 
 void GeneratedMessageFactory::RegisterFile(

+ 0 - 8
src/google/protobuf/message_lite.h

@@ -129,19 +129,11 @@ class ExplicitlyConstructed {
 // Default empty string object. Don't use this directly. Instead, call
 // GetEmptyString() to get the reference.
 LIBPROTOBUF_EXPORT extern ExplicitlyConstructed<::std::string> fixed_address_empty_string;
-LIBPROTOBUF_EXPORT extern ProtobufOnceType empty_string_once_init_;
-LIBPROTOBUF_EXPORT void InitEmptyString();
-
 
 LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyStringAlreadyInited() {
   return fixed_address_empty_string.get();
 }
 
-LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyString() {
-  ::google::protobuf::GoogleOnceInit(&empty_string_once_init_, &InitEmptyString);
-  return GetEmptyStringAlreadyInited();
-}
-
 LIBPROTOBUF_EXPORT size_t StringSpaceUsedExcludingSelfLong(const string& str);
 #endif  // SWIG
 }  // namespace internal

+ 20 - 44
src/google/protobuf/stubs/common.cc

@@ -339,66 +339,42 @@ namespace internal {
 typedef void OnShutdownFunc();
 struct ShutdownData {
   ~ShutdownData() {
-    for (int i = 0; i < functions.size(); i++) {
-      functions[i]();
-    }
-    for (int i = 0; i < strings.size(); i++) {
-      strings[i]->~string();
-    }
-    for (int i = 0; i < messages.size(); i++) {
-      messages[i]->~MessageLite();
-    }
+    std::reverse(functions.begin(), functions.end());
+    for (auto pair : functions) pair.first(pair.second);
   }
 
-  std::vector<void (*)()> functions;
-  std::vector<const std::string*> strings;
-  std::vector<const MessageLite*> messages;
+  static ShutdownData* get() {
+    static auto* data = new ShutdownData;
+    return data;
+  }
+
+  std::vector<std::pair<void (*)(const void*), const void*>> functions;
   Mutex mutex;
 };
 
-ShutdownData* shutdown_data = NULL;
-GOOGLE_PROTOBUF_DECLARE_ONCE(shutdown_functions_init);
-
-void InitShutdownFunctions() {
-  shutdown_data = new ShutdownData;
-}
-
-inline void InitShutdownFunctionsOnce() {
-  GoogleOnceInit(&shutdown_functions_init, &InitShutdownFunctions);
+static void RunZeroArgFunc(const void* arg) {
+  reinterpret_cast<void (*)()>(const_cast<void*>(arg))();
 }
 
 void OnShutdown(void (*func)()) {
-  InitShutdownFunctionsOnce();
-  MutexLock lock(&shutdown_data->mutex);
-  shutdown_data->functions.push_back(func);
+  OnShutdownRun(RunZeroArgFunc, reinterpret_cast<void*>(func));
 }
 
-void OnShutdownDestroyString(const std::string* ptr) {
-  InitShutdownFunctionsOnce();
+void OnShutdownRun(void (*f)(const void*), const void* arg) {
+  auto shutdown_data = ShutdownData::get();
   MutexLock lock(&shutdown_data->mutex);
-  shutdown_data->strings.push_back(ptr);
-}
-
-void OnShutdownDestroyMessage(const void* ptr) {
-  InitShutdownFunctionsOnce();
-  MutexLock lock(&shutdown_data->mutex);
-  shutdown_data->messages.push_back(static_cast<const MessageLite*>(ptr));
+  shutdown_data->functions.push_back(std::make_pair(f, arg));
 }
 
 }  // namespace internal
 
 void ShutdownProtobufLibrary() {
-  internal::InitShutdownFunctionsOnce();
-
-  // We don't need to lock shutdown_functions_mutex because it's up to the
-  // caller to make sure that no one is using the library before this is
-  // called.
-
-  // Make it safe to call this multiple times.
-  if (internal::shutdown_data == NULL) return;
-
-  delete internal::shutdown_data;
-  internal::shutdown_data = NULL;
+  // This function should be called only once, but accepts multiple calls.
+  static bool is_shutdown = false;
+  if (!is_shutdown) {
+    delete internal::ShutdownData::get();
+    is_shutdown = true;
+  }
 }
 
 #if PROTOBUF_USE_EXCEPTIONS

+ 10 - 5
src/google/protobuf/stubs/common.h

@@ -193,17 +193,22 @@ LIBPROTOBUF_EXPORT char* UTF8CoerceToStructurallyValid(
 //
 // It is safe to call this multiple times.  However, it is not safe to use
 // any other part of the protocol buffers library after
-// ShutdownProtobufLibrary() has been called.
+// ShutdownProtobufLibrary() has been called. Furthermore this call is not
+// thread safe, user needs to synchronize multiple calls.
 LIBPROTOBUF_EXPORT void ShutdownProtobufLibrary();
 
 namespace internal {
 
 // Register a function to be called when ShutdownProtocolBuffers() is called.
 LIBPROTOBUF_EXPORT void OnShutdown(void (*func)());
-// Destroy the string (call string destructor)
-LIBPROTOBUF_EXPORT void OnShutdownDestroyString(const std::string* ptr);
-// Destroy (not delete) the message
-LIBPROTOBUF_EXPORT void OnShutdownDestroyMessage(const void* ptr);
+// Run an arbitrary function on an arg
+LIBPROTOBUF_EXPORT void OnShutdownRun(void (*f)(const void*), const void* arg);
+
+template <typename T>
+T* OnShutdownDelete(T* p) {
+  OnShutdownRun([](const void* p) { delete static_cast<const T*>(p); }, p);
+  return p;
+}
 
 }  // namespace internal
 

+ 2 - 21
src/google/protobuf/unknown_field_set.cc

@@ -46,28 +46,9 @@
 namespace google {
 namespace protobuf {
 
-namespace {
-// This global instance is returned by unknown_fields() on any message class
-// when the object has no unknown fields. This is necessary because we now
-// instantiate the UnknownFieldSet dynamically only when required.
-UnknownFieldSet* default_unknown_field_set_instance_ = NULL;
-
-void DeleteDefaultUnknownFieldSet() {
-  delete default_unknown_field_set_instance_;
-}
-
-void InitDefaultUnknownFieldSet() {
-  default_unknown_field_set_instance_ = new UnknownFieldSet();
-  internal::OnShutdown(&DeleteDefaultUnknownFieldSet);
-}
-
-GOOGLE_PROTOBUF_DECLARE_ONCE(default_unknown_field_set_once_init_);
-}
-
 const UnknownFieldSet* UnknownFieldSet::default_instance() {
-  ::google::protobuf::GoogleOnceInit(&default_unknown_field_set_once_init_,
-                 &InitDefaultUnknownFieldSet);
-  return default_unknown_field_set_instance_;
+  static auto instance = internal::OnShutdownDelete(new UnknownFieldSet());
+  return instance;
 }
 
 void UnknownFieldSet::ClearFallback() {