Commit a9abc783 authored by Adam Cozzette's avatar Adam Cozzette

Fix initialization with Visual Studio

It appears that Visual Studio does not work well with std::once_flag
because it has a bug causing it to initialize that during dynamic
initialization instead of constant initialization. This change works
around the problem by using function static initializers instead.

@gerben-s originally wrote this change for the Google-internal codebase
but I am just cherry-picking it here.

This fixes #4773.
parent f7ada128
...@@ -479,15 +479,8 @@ typedef std::map<DescriptorIntPair, const FieldDescriptor*> ...@@ -479,15 +479,8 @@ typedef std::map<DescriptorIntPair, const FieldDescriptor*>
ExtensionsGroupedByDescriptorMap; ExtensionsGroupedByDescriptorMap;
typedef HASH_MAP<string, const SourceCodeInfo_Location*> LocationsByPathMap; typedef HASH_MAP<string, const SourceCodeInfo_Location*> LocationsByPathMap;
std::set<string>* allowed_proto3_extendees_ = NULL; std::set<string>* NewAllowedProto3Extendee() {
GOOGLE_PROTOBUF_DECLARE_ONCE(allowed_proto3_extendees_init_); auto allowed_proto3_extendees = new std::set<string>;
void DeleteAllowedProto3Extendee() {
delete allowed_proto3_extendees_;
}
void InitAllowedProto3Extendee() {
allowed_proto3_extendees_ = new std::set<string>;
const char* kOptionNames[] = { const char* kOptionNames[] = {
"FileOptions", "MessageOptions", "FieldOptions", "EnumOptions", "FileOptions", "MessageOptions", "FieldOptions", "EnumOptions",
"EnumValueOptions", "ServiceOptions", "MethodOptions", "OneofOptions"}; "EnumValueOptions", "ServiceOptions", "MethodOptions", "OneofOptions"};
...@@ -495,14 +488,13 @@ void InitAllowedProto3Extendee() { ...@@ -495,14 +488,13 @@ void InitAllowedProto3Extendee() {
// descriptor.proto has a different package name in opensource. We allow // descriptor.proto has a different package name in opensource. We allow
// both so the opensource protocol compiler can also compile internal // both so the opensource protocol compiler can also compile internal
// proto3 files with custom options. See: b/27567912 // proto3 files with custom options. See: b/27567912
allowed_proto3_extendees_->insert(string("google.protobuf.") + allowed_proto3_extendees->insert(string("google.protobuf.") +
kOptionNames[i]); kOptionNames[i]);
// Split the word to trick the opensource processing scripts so they // Split the word to trick the opensource processing scripts so they
// will keep the origial package name. // will keep the origial package name.
allowed_proto3_extendees_->insert(string("proto") + "2." + kOptionNames[i]); allowed_proto3_extendees->insert(string("proto") + "2." + kOptionNames[i]);
} }
return allowed_proto3_extendees;
google::protobuf::internal::OnShutdown(&DeleteAllowedProto3Extendee);
} }
// Checks whether the extendee type is allowed in proto3. // Checks whether the extendee type is allowed in proto3.
...@@ -510,9 +502,10 @@ void InitAllowedProto3Extendee() { ...@@ -510,9 +502,10 @@ void InitAllowedProto3Extendee() {
// instead of comparing the descriptor directly because the extensions may be // instead of comparing the descriptor directly because the extensions may be
// defined in a different pool. // defined in a different pool.
bool AllowedExtendeeInProto3(const string& name) { bool AllowedExtendeeInProto3(const string& name) {
::google::protobuf::GoogleOnceInit(&allowed_proto3_extendees_init_, &InitAllowedProto3Extendee); static auto allowed_proto3_extendees =
return allowed_proto3_extendees_->find(name) != internal::OnShutdownDelete(NewAllowedProto3Extendee());
allowed_proto3_extendees_->end(); return allowed_proto3_extendees->find(name) !=
allowed_proto3_extendees->end();
} }
} // anonymous namespace } // anonymous namespace
...@@ -829,31 +822,10 @@ FileDescriptorTables::FileDescriptorTables() ...@@ -829,31 +822,10 @@ FileDescriptorTables::FileDescriptorTables()
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() { inline const FileDescriptorTables& FileDescriptorTables::GetEmptyInstance() {
InitFileDescriptorTablesOnce(); static auto file_descriptor_tables =
return *file_descriptor_tables_; internal::OnShutdownDelete(new FileDescriptorTables());
return *file_descriptor_tables;
} }
void DescriptorPool::Tables::AddCheckpoint() { void DescriptorPool::Tables::AddCheckpoint() {
...@@ -1335,42 +1307,28 @@ bool DescriptorPool::InternalIsFileLoaded(const string& filename) const { ...@@ -1335,42 +1307,28 @@ bool DescriptorPool::InternalIsFileLoaded(const string& filename) const {
namespace { namespace {
EncodedDescriptorDatabase* GeneratedDatabase() {
EncodedDescriptorDatabase* generated_database_ = NULL; static auto generated_database =
DescriptorPool* generated_pool_ = NULL; internal::OnShutdownDelete(new EncodedDescriptorDatabase());
GOOGLE_PROTOBUF_DECLARE_ONCE(generated_pool_init_); return generated_database;
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);
} }
inline void InitGeneratedPoolOnce() { DescriptorPool* NewGeneratedPool() {
::google::protobuf::GoogleOnceInit(&generated_pool_init_, &InitGeneratedPool); auto generated_pool = new DescriptorPool(GeneratedDatabase());
generated_pool->InternalSetLazilyBuildDependencies();
return generated_pool;
} }
} // anonymous namespace } // anonymous namespace
const DescriptorPool* DescriptorPool::generated_pool() { DescriptorPool* DescriptorPool::internal_generated_pool() {
InitGeneratedPoolOnce(); static DescriptorPool* generated_pool =
return generated_pool_; internal::OnShutdownDelete(NewGeneratedPool());
return generated_pool;
} }
const DescriptorPool* DescriptorPool::generated_pool() {
return internal_generated_pool();
DescriptorPool* DescriptorPool::internal_generated_pool() {
InitGeneratedPoolOnce();
return generated_pool_;
} }
void DescriptorPool::InternalAddGeneratedFile( void DescriptorPool::InternalAddGeneratedFile(
...@@ -1397,8 +1355,7 @@ void DescriptorPool::InternalAddGeneratedFile( ...@@ -1397,8 +1355,7 @@ void DescriptorPool::InternalAddGeneratedFile(
// Therefore, when we parse one, we have to be very careful to avoid using // Therefore, when we parse one, we have to be very careful to avoid using
// any descriptor-based operations, since this might cause infinite recursion // any descriptor-based operations, since this might cause infinite recursion
// or deadlock. // or deadlock.
InitGeneratedPoolOnce(); GOOGLE_CHECK(GeneratedDatabase()->Add(encoded_file_descriptor, size));
GOOGLE_CHECK(generated_database_->Add(encoded_file_descriptor, size));
} }
......
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#include <tuple> #include <tuple>
#include <utility> #include <utility>
#include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/extension_set.h> #include <google/protobuf/extension_set.h>
#include <google/protobuf/message_lite.h> #include <google/protobuf/message_lite.h>
#include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/coded_stream.h>
...@@ -80,27 +79,17 @@ inline bool is_packable(WireFormatLite::WireType type) { ...@@ -80,27 +79,17 @@ inline bool is_packable(WireFormatLite::WireType type) {
// Registry stuff. // Registry stuff.
typedef hash_map<std::pair<const MessageLite*, int>, typedef hash_map<std::pair<const MessageLite*, int>,
ExtensionInfo> ExtensionRegistry; ExtensionInfo> ExtensionRegistry;
ExtensionRegistry* registry_ = NULL;
GOOGLE_PROTOBUF_DECLARE_ONCE(registry_init_);
void DeleteRegistry() { static const ExtensionRegistry* global_registry = nullptr;
delete registry_;
registry_ = NULL;
}
void InitRegistry() {
registry_ = new ExtensionRegistry;
OnShutdown(&DeleteRegistry);
}
// This function is only called at startup, so there is no need for thread- // This function is only called at startup, so there is no need for thread-
// safety. // safety.
void Register(const MessageLite* containing_type, void Register(const MessageLite* containing_type,
int number, ExtensionInfo info) { int number, ExtensionInfo info) {
::google::protobuf::GoogleOnceInit(&registry_init_, &InitRegistry); static auto local_static_registry = OnShutdownDelete(new ExtensionRegistry);
global_registry = local_static_registry;
if (!InsertIfNotPresent(registry_, std::make_pair(containing_type, number), if (!InsertIfNotPresent(local_static_registry,
info)) { std::make_pair(containing_type, number), info)) {
GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \"" GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \""
<< containing_type->GetTypeName() << containing_type->GetTypeName()
<< "\", field number " << number << "."; << "\", field number " << number << ".";
...@@ -109,9 +98,9 @@ void Register(const MessageLite* containing_type, ...@@ -109,9 +98,9 @@ void Register(const MessageLite* containing_type,
const ExtensionInfo* FindRegisteredExtension( const ExtensionInfo* FindRegisteredExtension(
const MessageLite* containing_type, int number) { const MessageLite* containing_type, int number) {
return (registry_ == NULL) return global_registry == nullptr
? NULL ? nullptr
: FindOrNull(*registry_, std::make_pair(containing_type, number)); : FindOrNull(*global_registry, std::make_pair(containing_type, number));
} }
} // namespace } // namespace
...@@ -1911,67 +1900,16 @@ void ExtensionSet::Erase(int key) { ...@@ -1911,67 +1900,16 @@ void ExtensionSet::Erase(int key) {
// ================================================================== // ==================================================================
// Default repeated field instances for iterator-compatible accessors // Default repeated field instances for iterator-compatible accessors
GOOGLE_PROTOBUF_DECLARE_ONCE(repeated_primitive_generic_type_traits_once_init_); const RepeatedPrimitiveDefaults* RepeatedPrimitiveDefaults::default_instance() {
GOOGLE_PROTOBUF_DECLARE_ONCE(repeated_string_type_traits_once_init_); static auto instance = OnShutdownDelete(new RepeatedPrimitiveDefaults);
GOOGLE_PROTOBUF_DECLARE_ONCE(repeated_message_generic_type_traits_once_init_); return instance;
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 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* const RepeatedStringTypeTraits::RepeatedFieldType*
RepeatedStringTypeTraits::default_repeated_field_ = NULL; RepeatedStringTypeTraits::GetDefaultRepeatedField() {
const RepeatedMessageGenericTypeTraits::RepeatedFieldType* static auto instance = OnShutdownDelete(new RepeatedFieldType);
RepeatedMessageGenericTypeTraits::default_repeated_field_ = NULL; return instance;
}
} // namespace internal } // namespace internal
} // namespace protobuf } // namespace protobuf
......
...@@ -880,18 +880,17 @@ class RepeatedPrimitiveTypeTraits { ...@@ -880,18 +880,17 @@ class RepeatedPrimitiveTypeTraits {
LIBPROTOBUF_EXPORT extern ProtobufOnceType repeated_primitive_generic_type_traits_once_init_; LIBPROTOBUF_EXPORT extern ProtobufOnceType repeated_primitive_generic_type_traits_once_init_;
class LIBPROTOBUF_EXPORT RepeatedPrimitiveGenericTypeTraits { class LIBPROTOBUF_EXPORT RepeatedPrimitiveDefaults {
private: private:
template<typename Type> friend class RepeatedPrimitiveTypeTraits; template<typename Type> friend class RepeatedPrimitiveTypeTraits;
static void InitializeDefaultRepeatedFields(); static const RepeatedPrimitiveDefaults* default_instance();
static void DestroyDefaultRepeatedFields(); RepeatedField<int32> default_repeated_field_int32_;
static const RepeatedField<int32>* default_repeated_field_int32_; RepeatedField<int64> default_repeated_field_int64_;
static const RepeatedField<int64>* default_repeated_field_int64_; RepeatedField<uint32> default_repeated_field_uint32_;
static const RepeatedField<uint32>* default_repeated_field_uint32_; RepeatedField<uint64> default_repeated_field_uint64_;
static const RepeatedField<uint64>* default_repeated_field_uint64_; RepeatedField<double> default_repeated_field_double_;
static const RepeatedField<double>* default_repeated_field_double_; RepeatedField<float> default_repeated_field_float_;
static const RepeatedField<float>* default_repeated_field_float_; RepeatedField<bool> default_repeated_field_bool_;
static const RepeatedField<bool>* default_repeated_field_bool_;
}; };
#define PROTOBUF_DEFINE_PRIMITIVE_TYPE(TYPE, METHOD) \ #define PROTOBUF_DEFINE_PRIMITIVE_TYPE(TYPE, METHOD) \
...@@ -919,11 +918,8 @@ template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Add( \ ...@@ -919,11 +918,8 @@ template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Add( \
} \ } \
template<> inline const RepeatedField<TYPE>* \ template<> inline const RepeatedField<TYPE>* \
RepeatedPrimitiveTypeTraits<TYPE>::GetDefaultRepeatedField() { \ RepeatedPrimitiveTypeTraits<TYPE>::GetDefaultRepeatedField() { \
::google::protobuf::GoogleOnceInit( \ return &RepeatedPrimitiveDefaults::default_instance() \
&repeated_primitive_generic_type_traits_once_init_, \ ->default_repeated_field_##TYPE##_; \
&RepeatedPrimitiveGenericTypeTraits::InitializeDefaultRepeatedFields); \
return RepeatedPrimitiveGenericTypeTraits:: \
default_repeated_field_##TYPE##_; \
} \ } \
template<> inline const RepeatedField<TYPE>& \ template<> inline const RepeatedField<TYPE>& \
RepeatedPrimitiveTypeTraits<TYPE>::GetRepeated(int number, \ RepeatedPrimitiveTypeTraits<TYPE>::GetRepeated(int number, \
...@@ -980,8 +976,6 @@ class LIBPROTOBUF_EXPORT StringTypeTraits { ...@@ -980,8 +976,6 @@ class LIBPROTOBUF_EXPORT StringTypeTraits {
} }
}; };
LIBPROTOBUF_EXPORT extern ProtobufOnceType repeated_string_type_traits_once_init_;
class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits { class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
public: public:
typedef const string& ConstType; typedef const string& ConstType;
...@@ -1024,11 +1018,7 @@ class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits { ...@@ -1024,11 +1018,7 @@ class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
is_packed, NULL)); is_packed, NULL));
} }
static const RepeatedFieldType* GetDefaultRepeatedField() { static const RepeatedFieldType* GetDefaultRepeatedField();
::google::protobuf::GoogleOnceInit(&repeated_string_type_traits_once_init_,
&InitializeDefaultRepeatedFields);
return default_repeated_field_;
}
template <typename ExtendeeT> template <typename ExtendeeT>
static void Register(int number, FieldType type, bool is_packed) { static void Register(int number, FieldType type, bool is_packed) {
...@@ -1039,7 +1029,6 @@ class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits { ...@@ -1039,7 +1029,6 @@ class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
private: private:
static void InitializeDefaultRepeatedFields(); static void InitializeDefaultRepeatedFields();
static void DestroyDefaultRepeatedFields(); static void DestroyDefaultRepeatedFields();
static const RepeatedFieldType *default_repeated_field_;
}; };
// ------------------------------------------------------------------- // -------------------------------------------------------------------
...@@ -1230,28 +1219,11 @@ class RepeatedMessageTypeTraits { ...@@ -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 template<typename Type> inline
const typename RepeatedMessageTypeTraits<Type>::RepeatedFieldType* const typename RepeatedMessageTypeTraits<Type>::RepeatedFieldType*
RepeatedMessageTypeTraits<Type>::GetDefaultRepeatedField() { RepeatedMessageTypeTraits<Type>::GetDefaultRepeatedField() {
::google::protobuf::GoogleOnceInit( static auto instance = OnShutdownDelete(new RepeatedFieldType);
&repeated_message_generic_type_traits_once_init_, return instance;
&RepeatedMessageGenericTypeTraits::InitializeDefaultRepeatedFields);
return reinterpret_cast<const RepeatedFieldType*>(
RepeatedMessageGenericTypeTraits::default_repeated_field_);
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
......
...@@ -2327,32 +2327,26 @@ class AssignDescriptorsHelper { ...@@ -2327,32 +2327,26 @@ class AssignDescriptorsHelper {
// automatically delete the allocated reflection. MetadataOwner owns // automatically delete the allocated reflection. MetadataOwner owns
// all the allocated reflection instances. // all the allocated reflection instances.
struct MetadataOwner { 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) { void AddArray(const Metadata* begin, const Metadata* end) {
MutexLock lock(&mu_); MutexLock lock(&mu_);
metadata_arrays_.push_back(std::make_pair(begin, end)); metadata_arrays_.push_back(std::make_pair(begin, end));
} }
static MetadataOwner* Instance() { static MetadataOwner* Instance() {
static MetadataOwner* res = new MetadataOwner; static MetadataOwner* res = OnShutdownDelete(new MetadataOwner);
return res; return res;
} }
private: private:
// Use the constructor to register the shutdown code. Because c++ makes sure MetadataOwner() = default; // private because singleton
// 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();
}
Mutex mu_; Mutex mu_;
std::vector<std::pair<const Metadata*, const Metadata*> > metadata_arrays_; std::vector<std::pair<const Metadata*, const Metadata*> > metadata_arrays_;
......
...@@ -57,6 +57,12 @@ namespace google { ...@@ -57,6 +57,12 @@ namespace google {
namespace protobuf { namespace protobuf {
namespace internal { 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() { double Infinity() {
return std::numeric_limits<double>::infinity(); return std::numeric_limits<double>::infinity();
...@@ -65,14 +71,15 @@ double NaN() { ...@@ -65,14 +71,15 @@ double NaN() {
return std::numeric_limits<double>::quiet_NaN(); return std::numeric_limits<double>::quiet_NaN();
} }
ExplicitlyConstructed<::std::string> fixed_address_empty_string; static bool InitProtobufDefaultsImpl() {
GOOGLE_PROTOBUF_DECLARE_ONCE(empty_string_once_init_);
void DeleteEmptyString() { fixed_address_empty_string.Destruct(); }
void InitEmptyString() {
fixed_address_empty_string.DefaultConstruct(); 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) { size_t StringSpaceUsedExcludingSelfLong(const string& str) {
...@@ -86,12 +93,6 @@ size_t StringSpaceUsedExcludingSelfLong(const string& str) { ...@@ -86,12 +93,6 @@ size_t StringSpaceUsedExcludingSelfLong(const string& str) {
} }
} }
void InitProtobufDefaults() {
GetEmptyString();
}
template <typename T> template <typename T>
const T& Get(const void* ptr) { const T& Get(const void* ptr) {
return *static_cast<const T*>(ptr); return *static_cast<const T*>(ptr);
......
...@@ -109,6 +109,13 @@ namespace internal { ...@@ -109,6 +109,13 @@ namespace internal {
LIBPROTOBUF_EXPORT double Infinity(); LIBPROTOBUF_EXPORT double Infinity();
LIBPROTOBUF_EXPORT double NaN(); 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 // 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 // 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) { ...@@ -137,8 +144,6 @@ bool AllAreInitializedWeak(const ::google::protobuf::RepeatedPtrField<T>& t) {
return true; return true;
} }
LIBPROTOBUF_EXPORT void InitProtobufDefaults();
struct LIBPROTOBUF_EXPORT FieldMetadata { struct LIBPROTOBUF_EXPORT FieldMetadata {
uint32 offset; // offset of this field in the struct uint32 offset; // offset of this field in the struct
uint32 tag; // field * 8 + wire_type uint32 tag; // field * 8 + wire_type
...@@ -368,6 +373,17 @@ inline void InitSCC(SCCInfoBase* scc) { ...@@ -368,6 +373,17 @@ inline void InitSCC(SCCInfoBase* scc) {
if (GOOGLE_PREDICT_FALSE(status != SCCInfoBase::kInitialized)) InitSCCImpl(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 internal
} // namespace protobuf } // namespace protobuf
......
...@@ -262,9 +262,6 @@ namespace { ...@@ -262,9 +262,6 @@ namespace {
class GeneratedMessageFactory : public MessageFactory { class GeneratedMessageFactory : public MessageFactory {
public: public:
GeneratedMessageFactory();
~GeneratedMessageFactory();
static GeneratedMessageFactory* singleton(); static GeneratedMessageFactory* singleton();
typedef void RegistrationFunc(const string&); typedef void RegistrationFunc(const string&);
...@@ -284,25 +281,9 @@ class GeneratedMessageFactory : public MessageFactory { ...@@ -284,25 +281,9 @@ class GeneratedMessageFactory : public MessageFactory {
hash_map<const Descriptor*, const Message*> type_map_; 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() { GeneratedMessageFactory* GeneratedMessageFactory::singleton() {
::google::protobuf::GoogleOnceInit(&generated_message_factory_once_init_, static auto instance = internal::OnShutdownDelete(new GeneratedMessageFactory);
&InitGeneratedMessageFactory); return instance;
return generated_message_factory_;
} }
void GeneratedMessageFactory::RegisterFile( void GeneratedMessageFactory::RegisterFile(
......
...@@ -129,19 +129,11 @@ class ExplicitlyConstructed { ...@@ -129,19 +129,11 @@ class ExplicitlyConstructed {
// Default empty string object. Don't use this directly. Instead, call // Default empty string object. Don't use this directly. Instead, call
// GetEmptyString() to get the reference. // GetEmptyString() to get the reference.
LIBPROTOBUF_EXPORT extern ExplicitlyConstructed<::std::string> fixed_address_empty_string; 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() { LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyStringAlreadyInited() {
return fixed_address_empty_string.get(); 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); LIBPROTOBUF_EXPORT size_t StringSpaceUsedExcludingSelfLong(const string& str);
#endif // SWIG #endif // SWIG
} // namespace internal } // namespace internal
......
...@@ -339,66 +339,42 @@ namespace internal { ...@@ -339,66 +339,42 @@ namespace internal {
typedef void OnShutdownFunc(); typedef void OnShutdownFunc();
struct ShutdownData { struct ShutdownData {
~ShutdownData() { ~ShutdownData() {
for (int i = 0; i < functions.size(); i++) { std::reverse(functions.begin(), functions.end());
functions[i](); for (auto pair : functions) pair.first(pair.second);
}
for (int i = 0; i < strings.size(); i++) {
strings[i]->~string();
}
for (int i = 0; i < messages.size(); i++) {
messages[i]->~MessageLite();
}
} }
std::vector<void (*)()> functions; static ShutdownData* get() {
std::vector<const std::string*> strings; static auto* data = new ShutdownData;
std::vector<const MessageLite*> messages; return data;
}
std::vector<std::pair<void (*)(const void*), const void*>> functions;
Mutex mutex; Mutex mutex;
}; };
ShutdownData* shutdown_data = NULL; static void RunZeroArgFunc(const void* arg) {
GOOGLE_PROTOBUF_DECLARE_ONCE(shutdown_functions_init); reinterpret_cast<void (*)()>(const_cast<void*>(arg))();
void InitShutdownFunctions() {
shutdown_data = new ShutdownData;
}
inline void InitShutdownFunctionsOnce() {
GoogleOnceInit(&shutdown_functions_init, &InitShutdownFunctions);
} }
void OnShutdown(void (*func)()) { void OnShutdown(void (*func)()) {
InitShutdownFunctionsOnce(); OnShutdownRun(RunZeroArgFunc, reinterpret_cast<void*>(func));
MutexLock lock(&shutdown_data->mutex);
shutdown_data->functions.push_back(func);
} }
void OnShutdownDestroyString(const std::string* ptr) { void OnShutdownRun(void (*f)(const void*), const void* arg) {
InitShutdownFunctionsOnce(); auto shutdown_data = ShutdownData::get();
MutexLock lock(&shutdown_data->mutex); MutexLock lock(&shutdown_data->mutex);
shutdown_data->strings.push_back(ptr); shutdown_data->functions.push_back(std::make_pair(f, arg));
}
void OnShutdownDestroyMessage(const void* ptr) {
InitShutdownFunctionsOnce();
MutexLock lock(&shutdown_data->mutex);
shutdown_data->messages.push_back(static_cast<const MessageLite*>(ptr));
} }
} // namespace internal } // namespace internal
void ShutdownProtobufLibrary() { void ShutdownProtobufLibrary() {
internal::InitShutdownFunctionsOnce(); // This function should be called only once, but accepts multiple calls.
static bool is_shutdown = false;
// We don't need to lock shutdown_functions_mutex because it's up to the if (!is_shutdown) {
// caller to make sure that no one is using the library before this is delete internal::ShutdownData::get();
// called. is_shutdown = true;
}
// Make it safe to call this multiple times.
if (internal::shutdown_data == NULL) return;
delete internal::shutdown_data;
internal::shutdown_data = NULL;
} }
#if PROTOBUF_USE_EXCEPTIONS #if PROTOBUF_USE_EXCEPTIONS
......
...@@ -193,17 +193,22 @@ LIBPROTOBUF_EXPORT char* UTF8CoerceToStructurallyValid( ...@@ -193,17 +193,22 @@ LIBPROTOBUF_EXPORT char* UTF8CoerceToStructurallyValid(
// //
// It is safe to call this multiple times. However, it is not safe to use // It is safe to call this multiple times. However, it is not safe to use
// any other part of the protocol buffers library after // 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(); LIBPROTOBUF_EXPORT void ShutdownProtobufLibrary();
namespace internal { namespace internal {
// Register a function to be called when ShutdownProtocolBuffers() is called. // Register a function to be called when ShutdownProtocolBuffers() is called.
LIBPROTOBUF_EXPORT void OnShutdown(void (*func)()); LIBPROTOBUF_EXPORT void OnShutdown(void (*func)());
// Destroy the string (call string destructor) // Run an arbitrary function on an arg
LIBPROTOBUF_EXPORT void OnShutdownDestroyString(const std::string* ptr); LIBPROTOBUF_EXPORT void OnShutdownRun(void (*f)(const void*), const void* arg);
// Destroy (not delete) the message
LIBPROTOBUF_EXPORT void OnShutdownDestroyMessage(const void* ptr); template <typename T>
T* OnShutdownDelete(T* p) {
OnShutdownRun([](const void* p) { delete static_cast<const T*>(p); }, p);
return p;
}
} // namespace internal } // namespace internal
......
...@@ -46,28 +46,9 @@ ...@@ -46,28 +46,9 @@
namespace google { namespace google {
namespace protobuf { 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() { const UnknownFieldSet* UnknownFieldSet::default_instance() {
::google::protobuf::GoogleOnceInit(&default_unknown_field_set_once_init_, static auto instance = internal::OnShutdownDelete(new UnknownFieldSet());
&InitDefaultUnknownFieldSet); return instance;
return default_unknown_field_set_instance_;
} }
void UnknownFieldSet::ClearFallback() { void UnknownFieldSet::ClearFallback() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment