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 15 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;
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_);

Loading…
Cancel
Save