Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix initialization with Visual Studio #4878

Merged
merged 1 commit into from Jul 9, 2018
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

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.
  • Loading branch information...
acozzette committed Jul 6, 2018
commit a9abc7831e45257d334cfa682746b6cadf9e95d9
@@ -479,40 +479,33 @@ 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"};
for (int i = 0; i < GOOGLE_ARRAYSIZE(kOptionNames); ++i) {
// 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.
// Only extensions to descriptor options are allowed. We use name comparison
// 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));
}


@@ -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
@@ -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;
}

// -------------------------------------------------------------------
Oops, something went wrong.
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.