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.
This commit is contained in:
parent
f7ada1280f
commit
a9abc7831e
@ -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() {
|
|||||||
// 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() {
|
|||||||
// 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()
|
|||||||
|
|
||||||
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 {
|
|||||||
|
|
||||||
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() {
|
DescriptorPool* NewGeneratedPool() {
|
||||||
generated_database_ = new EncodedDescriptorDatabase;
|
auto generated_pool = new DescriptorPool(GeneratedDatabase());
|
||||||
generated_pool_ = new DescriptorPool(generated_database_);
|
generated_pool->InternalSetLazilyBuildDependencies();
|
||||||
generated_pool_->InternalSetLazilyBuildDependencies();
|
return generated_pool;
|
||||||
|
|
||||||
internal::OnShutdown(&DeleteGeneratedPool);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void InitGeneratedPoolOnce() {
|
|
||||||
::google::protobuf::GoogleOnceInit(&generated_pool_init_, &InitGeneratedPool);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // 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(
|
|||||||
// 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 @@
|
|||||||
#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) {
|
|||||||
// 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(®istry_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,
|
|||||||
|
|
||||||
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) {
|
|||||||
// ==================================================================
|
// ==================================================================
|
||||||
// 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 {
|
|||||||
|
|
||||||
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( \
|
|||||||
} \
|
} \
|
||||||
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 {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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 {
|
|||||||
// 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 {
|
|||||||
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() {
|
|||||||
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) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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 {
|
|||||||
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) {
|
|||||||
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) {
|
|||||||
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 {
|
|||||||
|
|
||||||
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 {
|
|||||||
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 {
|
|||||||
// 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 {
|
|||||||
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(
|
|||||||
//
|
//
|
||||||
// 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 @@
|
|||||||
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() {
|
||||||
|
Loading…
Reference in New Issue
Block a user