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*>
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));
}
......
......@@ -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;
}
// -------------------------------------------------------------------
......
......@@ -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_;
......
......@@ -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);
......
......@@ -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
......
......@@ -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(
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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() {
......
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