aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Adam Cozzette <acozzette@gmail.com>2018-07-09 09:35:48 -0700
committerGravatar GitHub <noreply@github.com>2018-07-09 09:35:48 -0700
commite1845779ed1115dd61eb2a3b8f0a78c252ca5b2b (patch)
treefdb892e4e34269f6b3bbb6f629a912d4c63c2d70
parentf7ada1280fac4af717d478e6a9765d3f02b418b3 (diff)
parenta9abc7831e45257d334cfa682746b6cadf9e95d9 (diff)
Merge pull request #4878 from acozzette/fix-msvc-initialization
Fix initialization with Visual Studio
-rw-r--r--src/google/protobuf/descriptor.cc97
-rw-r--r--src/google/protobuf/extension_set.cc92
-rw-r--r--src/google/protobuf/extension_set.h56
-rw-r--r--src/google/protobuf/generated_message_reflection.cc26
-rw-r--r--src/google/protobuf/generated_message_util.cc27
-rw-r--r--src/google/protobuf/generated_message_util.h20
-rw-r--r--src/google/protobuf/message.cc23
-rw-r--r--src/google/protobuf/message_lite.h8
-rwxr-xr-xsrc/google/protobuf/stubs/common.cc64
-rw-r--r--src/google/protobuf/stubs/common.h15
-rw-r--r--src/google/protobuf/unknown_field_set.cc23
11 files changed, 132 insertions, 319 deletions
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index 83eae519..fc3a9c77 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/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));
}
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
index b587b38f..cb205c4f 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/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
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index c4796629..a1535baa 100644
--- a/src/google/protobuf/extension_set.h
+++ b/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;
}
// -------------------------------------------------------------------
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index 247f772c..74ad00e7 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/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_;
diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc
index dac8ca90..e0241361 100644
--- a/src/google/protobuf/generated_message_util.cc
+++ b/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);
diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h
index 706df383..04f68a6e 100644
--- a/src/google/protobuf/generated_message_util.h
+++ b/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
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index 810db233..9b758080 100644
--- a/src/google/protobuf/message.cc
+++ b/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(
diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h
index 4cbec330..b8644142 100644
--- a/src/google/protobuf/message_lite.h
+++ b/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
diff --git a/src/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc
index 33d24c57..6544c6ed 100755
--- a/src/google/protobuf/stubs/common.cc
+++ b/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
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index 5d320764..f505f46a 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/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
diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc
index 0ada85e5..35f24e7a 100644
--- a/src/google/protobuf/unknown_field_set.cc
+++ b/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() {