Commit bdbb8630 authored by temporal's avatar temporal

Ensure that 'once' objects are declared using the macro. This is either the…

Ensure that 'once' objects are declared using the macro.  This is either the third or fourth time I've screwed this up when down-integrating, because our internal code does not require the macro (it's not portable) and on Linux a pthread_once_t that is zero-initialized just happens to work.  So, I only discover the problem when I test on Mac, then kick myself for making the same mistake yet again.  No more!  This time, I have renamed GoogleOnceType to ProtobufOnceType, thus making the type name differ from our internal code.  As a result, if you don't update the decls to use the macros, they won't compile.  Hah!  Take that, future self!
parent 91218afc
......@@ -799,7 +799,7 @@ namespace {
EncodedDescriptorDatabase* generated_database_ = NULL;
DescriptorPool* generated_pool_ = NULL;
GoogleOnceType generated_pool_init_;
GOOGLE_PROTOBUF_DECLARE_ONCE(generated_pool_init_);
void DeleteGeneratedPool() {
delete generated_database_;
......
......@@ -62,7 +62,7 @@ inline WireFormatLite::CppType cpp_type(FieldType type) {
typedef hash_map<pair<const MessageLite*, int>,
ExtensionInfo> ExtensionRegistry;
ExtensionRegistry* registry_ = NULL;
GoogleOnceType registry_init_;
GOOGLE_PROTOBUF_DECLARE_ONCE(registry_init_);
void DeleteRegistry() {
delete registry_;
......
......@@ -212,7 +212,7 @@ class GeneratedMessageFactory : public MessageFactory {
};
GeneratedMessageFactory* generated_message_factory_ = NULL;
GoogleOnceType generated_message_factory_once_init_;
GOOGLE_PROTOBUF_DECLARE_ONCE(generated_message_factory_once_init_);
void ShutdownGeneratedMessageFactory() {
delete generated_message_factory_;
......
......@@ -46,33 +46,33 @@ namespace protobuf {
#ifdef _WIN32
struct GoogleOnceInternal {
GoogleOnceInternal() {
struct ProtobufOnceInternal {
ProtobufOnceInternal() {
InitializeCriticalSection(&critical_section);
}
~GoogleOnceInternal() {
~ProtobufOnceInternal() {
DeleteCriticalSection(&critical_section);
}
CRITICAL_SECTION critical_section;
};
GoogleOnceType::~GoogleOnceType()
ProtobufOnceType::~ProtobufOnceType()
{
delete internal_;
internal_ = NULL;
}
GoogleOnceType::GoogleOnceType() {
ProtobufOnceType::ProtobufOnceType() {
// internal_ may be non-NULL if Init() was already called.
if (internal_ == NULL) internal_ = new GoogleOnceInternal;
if (internal_ == NULL) internal_ = new ProtobufOnceInternal;
}
void GoogleOnceType::Init(void (*init_func)()) {
void ProtobufOnceType::Init(void (*init_func)()) {
// internal_ may be NULL if we're still in dynamic initialization and the
// constructor has not been called yet. As mentioned in once.h, we assume
// that the program is still single-threaded at this time, and therefore it
// should be safe to initialize internal_ like so.
if (internal_ == NULL) internal_ = new GoogleOnceInternal;
if (internal_ == NULL) internal_ = new ProtobufOnceInternal;
EnterCriticalSection(&internal_->critical_section);
if (!initialized_) {
......
......@@ -38,13 +38,13 @@
// This is basically a portable version of pthread_once().
//
// This header declares three things:
// * A type called GoogleOnceType.
// * A type called ProtobufOnceType.
// * A macro GOOGLE_PROTOBUF_DECLARE_ONCE() which declares a variable of type
// GoogleOnceType. This is the only legal way to declare such a variable.
// ProtobufOnceType. This is the only legal way to declare such a variable.
// The macro may only be used at the global scope (you cannot create local
// or class member variables of this type).
// * A function GogoleOnceInit(GoogleOnceType* once, void (*init_func)()).
// This function, when invoked multiple times given the same GoogleOnceType
// * A function GogoleOnceInit(ProtobufOnceType* once, void (*init_func)()).
// This function, when invoked multiple times given the same ProtobufOnceType
// object, will invoke init_func on the first call only, and will make sure
// none of the calls return before that first call to init_func has finished.
//
......@@ -83,21 +83,21 @@ namespace protobuf {
#ifdef _WIN32
struct GoogleOnceInternal;
struct ProtobufOnceInternal;
struct LIBPROTOBUF_EXPORT GoogleOnceType {
GoogleOnceType();
~GoogleOnceType();
struct LIBPROTOBUF_EXPORT ProtobufOnceType {
ProtobufOnceType();
~ProtobufOnceType();
void Init(void (*init_func)());
volatile bool initialized_;
GoogleOnceInternal* internal_;
ProtobufOnceInternal* internal_;
};
#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \
::google::protobuf::GoogleOnceType NAME
::google::protobuf::ProtobufOnceType NAME
inline void GoogleOnceInit(GoogleOnceType* once, void (*init_func)()) {
inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) {
// Note: Double-checked locking is safe on x86.
if (!once->initialized_) {
once->Init(init_func);
......@@ -106,12 +106,12 @@ inline void GoogleOnceInit(GoogleOnceType* once, void (*init_func)()) {
#else
typedef pthread_once_t GoogleOnceType;
typedef pthread_once_t ProtobufOnceType;
#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \
pthread_once_t NAME = PTHREAD_ONCE_INIT
inline void GoogleOnceInit(GoogleOnceType* once, void (*init_func)()) {
inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) {
pthread_once(once, init_func);
}
......
......@@ -52,10 +52,10 @@ class OnceInitTest : public testing::Test {
current_test_ = this;
}
// Since GoogleOnceType is only allowed to be allocated in static storage,
// each test must use a different pair of GoogleOnceType objects which it
// Since ProtobufOnceType is only allowed to be allocated in static storage,
// each test must use a different pair of ProtobufOnceType objects which it
// must declare itself.
void SetOnces(GoogleOnceType* once, GoogleOnceType* recursive_once) {
void SetOnces(ProtobufOnceType* once, ProtobufOnceType* recursive_once) {
once_ = once;
recursive_once_ = recursive_once;
}
......@@ -155,8 +155,8 @@ class OnceInitTest : public testing::Test {
Mutex mutex_;
Mutex init_blocker_;
State state_;
GoogleOnceType* once_;
GoogleOnceType* recursive_once_;
ProtobufOnceType* once_;
ProtobufOnceType* recursive_once_;
void Init() {
MutexLock lock(&mutex_);
......
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