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!

pull/3335/head
temporal 16 years ago
parent 91218afc67
commit bdbb863099
  1. 2
      src/google/protobuf/descriptor.cc
  2. 2
      src/google/protobuf/extension_set.cc
  3. 2
      src/google/protobuf/message.cc
  4. 16
      src/google/protobuf/stubs/once.cc
  5. 26
      src/google/protobuf/stubs/once.h
  6. 10
      src/google/protobuf/stubs/once_unittest.cc

@ -799,7 +799,7 @@ namespace {
EncodedDescriptorDatabase* generated_database_ = NULL; EncodedDescriptorDatabase* generated_database_ = NULL;
DescriptorPool* generated_pool_ = NULL; DescriptorPool* generated_pool_ = NULL;
GoogleOnceType generated_pool_init_; GOOGLE_PROTOBUF_DECLARE_ONCE(generated_pool_init_);
void DeleteGeneratedPool() { void DeleteGeneratedPool() {
delete generated_database_; delete generated_database_;

@ -62,7 +62,7 @@ inline WireFormatLite::CppType cpp_type(FieldType type) {
typedef hash_map<pair<const MessageLite*, int>, typedef hash_map<pair<const MessageLite*, int>,
ExtensionInfo> ExtensionRegistry; ExtensionInfo> ExtensionRegistry;
ExtensionRegistry* registry_ = NULL; ExtensionRegistry* registry_ = NULL;
GoogleOnceType registry_init_; GOOGLE_PROTOBUF_DECLARE_ONCE(registry_init_);
void DeleteRegistry() { void DeleteRegistry() {
delete registry_; delete registry_;

@ -212,7 +212,7 @@ class GeneratedMessageFactory : public MessageFactory {
}; };
GeneratedMessageFactory* generated_message_factory_ = NULL; GeneratedMessageFactory* generated_message_factory_ = NULL;
GoogleOnceType generated_message_factory_once_init_; GOOGLE_PROTOBUF_DECLARE_ONCE(generated_message_factory_once_init_);
void ShutdownGeneratedMessageFactory() { void ShutdownGeneratedMessageFactory() {
delete generated_message_factory_; delete generated_message_factory_;

@ -46,33 +46,33 @@ namespace protobuf {
#ifdef _WIN32 #ifdef _WIN32
struct GoogleOnceInternal { struct ProtobufOnceInternal {
GoogleOnceInternal() { ProtobufOnceInternal() {
InitializeCriticalSection(&critical_section); InitializeCriticalSection(&critical_section);
} }
~GoogleOnceInternal() { ~ProtobufOnceInternal() {
DeleteCriticalSection(&critical_section); DeleteCriticalSection(&critical_section);
} }
CRITICAL_SECTION critical_section; CRITICAL_SECTION critical_section;
}; };
GoogleOnceType::~GoogleOnceType() ProtobufOnceType::~ProtobufOnceType()
{ {
delete internal_; delete internal_;
internal_ = NULL; internal_ = NULL;
} }
GoogleOnceType::GoogleOnceType() { ProtobufOnceType::ProtobufOnceType() {
// internal_ may be non-NULL if Init() was already called. // 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 // 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 // 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 // that the program is still single-threaded at this time, and therefore it
// should be safe to initialize internal_ like so. // should be safe to initialize internal_ like so.
if (internal_ == NULL) internal_ = new GoogleOnceInternal; if (internal_ == NULL) internal_ = new ProtobufOnceInternal;
EnterCriticalSection(&internal_->critical_section); EnterCriticalSection(&internal_->critical_section);
if (!initialized_) { if (!initialized_) {

@ -38,13 +38,13 @@
// This is basically a portable version of pthread_once(). // This is basically a portable version of pthread_once().
// //
// This header declares three things: // 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 // * 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 // The macro may only be used at the global scope (you cannot create local
// or class member variables of this type). // or class member variables of this type).
// * A function GogoleOnceInit(GoogleOnceType* once, void (*init_func)()). // * A function GogoleOnceInit(ProtobufOnceType* once, void (*init_func)()).
// This function, when invoked multiple times given the same GoogleOnceType // This function, when invoked multiple times given the same ProtobufOnceType
// object, will invoke init_func on the first call only, and will make sure // 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. // none of the calls return before that first call to init_func has finished.
// //
@ -83,21 +83,21 @@ namespace protobuf {
#ifdef _WIN32 #ifdef _WIN32
struct GoogleOnceInternal; struct ProtobufOnceInternal;
struct LIBPROTOBUF_EXPORT GoogleOnceType { struct LIBPROTOBUF_EXPORT ProtobufOnceType {
GoogleOnceType(); ProtobufOnceType();
~GoogleOnceType(); ~ProtobufOnceType();
void Init(void (*init_func)()); void Init(void (*init_func)());
volatile bool initialized_; volatile bool initialized_;
GoogleOnceInternal* internal_; ProtobufOnceInternal* internal_;
}; };
#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \ #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. // Note: Double-checked locking is safe on x86.
if (!once->initialized_) { if (!once->initialized_) {
once->Init(init_func); once->Init(init_func);
@ -106,12 +106,12 @@ inline void GoogleOnceInit(GoogleOnceType* once, void (*init_func)()) {
#else #else
typedef pthread_once_t GoogleOnceType; typedef pthread_once_t ProtobufOnceType;
#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \ #define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \
pthread_once_t NAME = PTHREAD_ONCE_INIT 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); pthread_once(once, init_func);
} }

@ -52,10 +52,10 @@ class OnceInitTest : public testing::Test {
current_test_ = this; current_test_ = this;
} }
// Since GoogleOnceType is only allowed to be allocated in static storage, // Since ProtobufOnceType is only allowed to be allocated in static storage,
// each test must use a different pair of GoogleOnceType objects which it // each test must use a different pair of ProtobufOnceType objects which it
// must declare itself. // must declare itself.
void SetOnces(GoogleOnceType* once, GoogleOnceType* recursive_once) { void SetOnces(ProtobufOnceType* once, ProtobufOnceType* recursive_once) {
once_ = once; once_ = once;
recursive_once_ = recursive_once; recursive_once_ = recursive_once;
} }
@ -155,8 +155,8 @@ class OnceInitTest : public testing::Test {
Mutex mutex_; Mutex mutex_;
Mutex init_blocker_; Mutex init_blocker_;
State state_; State state_;
GoogleOnceType* once_; ProtobufOnceType* once_;
GoogleOnceType* recursive_once_; ProtobufOnceType* recursive_once_;
void Init() { void Init() {
MutexLock lock(&mutex_); MutexLock lock(&mutex_);

Loading…
Cancel
Save