From a3b2a6da25a76f17c73d31def3952feb0fd2296e Mon Sep 17 00:00:00 2001 From: Jeff Davidson Date: Mon, 15 Sep 2014 16:29:06 -0700 Subject: Update protobuf library from 2.3 to 2.6. Copied in all files from the open source protobuf project at commit edc5994525c79cd1919859a370837a6ff7c8e308, removing files which have been renamed (COPYING.txt -> LICENSE, README.txt -> README.md). Removed 2.3 prebuilts, which is an approach that will not work due to incompatibility with the 2.6 runtime. Merged in micro/nano-specific changes in the following files: -Android.mk - updated list of C++/Java sources, bumped versions -java/README.txt - merged in micro/nano instructions, bumped versions -java/pom.xml - merged in micro/nano build rules, set packaging to jar -src/Makefile.am - merged in references to micro/nano generators -src/google/protobuf/compiler/javamicro/javamicro_file.h - imported google/protobuf/compiler/code_generator.h and removed redundant OutputDirectory class. -src/google/protobuf/compiler/javanano/javanano_file.h - same -Replaced instances of vector with std::vector as needed to get libprotobuf-cpp-full to compile. Plan to upstream this fix per discussion with protobuf maintainers. Reran autogen.sh to update ./configure and associated scripts. Change-Id: I949d32fb5126f1c05e2a6ed48f6636a4a9b15a48 --- src/google/protobuf/stubs/once.h | 101 ++++++++++++++++++++++++++++----------- 1 file changed, 72 insertions(+), 29 deletions(-) (limited to 'src/google/protobuf/stubs/once.h') diff --git a/src/google/protobuf/stubs/once.h b/src/google/protobuf/stubs/once.h index 0dee407..86a4c01 100644 --- a/src/google/protobuf/stubs/once.h +++ b/src/google/protobuf/stubs/once.h @@ -37,16 +37,22 @@ // // This is basically a portable version of pthread_once(). // -// This header declares three things: +// This header declares: // * A type called ProtobufOnceType. // * A macro GOOGLE_PROTOBUF_DECLARE_ONCE() which declares a variable of type // 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(ProtobufOnceType* once, void (*init_func)()). +// The macro may only be used at the global scope (you cannot create local or +// class member variables of this type). +// * A function GoogleOnceInit(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. +// * The user can provide a parameter which GoogleOnceInit() forwards to the +// user-provided function when it is called. Usage example: +// int a = 10; +// GoogleOnceInit(&my_once, &MyFunctionExpectingIntArgument, &a); +// * This implementation guarantees that ProtobufOnceType is a POD (i.e. no +// static initializer generated). // // This implements a way to perform lazy initialization. It's more efficient // than using mutexes as no lock is needed if initialization has already @@ -72,50 +78,87 @@ #ifndef GOOGLE_PROTOBUF_STUBS_ONCE_H__ #define GOOGLE_PROTOBUF_STUBS_ONCE_H__ +#include #include -#ifndef _WIN32 -#include -#endif - namespace google { namespace protobuf { -#ifdef _WIN32 - -struct ProtobufOnceInternal; +#ifdef GOOGLE_PROTOBUF_NO_THREAD_SAFETY -struct LIBPROTOBUF_EXPORT ProtobufOnceType { - ProtobufOnceType(); - ~ProtobufOnceType(); - void Init(void (*init_func)()); +typedef bool ProtobufOnceType; - volatile bool initialized_; - ProtobufOnceInternal* internal_; -}; - -#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \ - ::google::protobuf::ProtobufOnceType NAME +#define GOOGLE_PROTOBUF_ONCE_INIT false inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) { - // Note: Double-checked locking is safe on x86. - if (!once->initialized_) { - once->Init(init_func); + if (!*once) { + *once = true; + init_func(); + } +} + +template +inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)(Arg), + Arg arg) { + if (!*once) { + *once = true; + init_func(arg); } } #else -typedef pthread_once_t ProtobufOnceType; +enum { + ONCE_STATE_UNINITIALIZED = 0, + ONCE_STATE_EXECUTING_CLOSURE = 1, + ONCE_STATE_DONE = 2 +}; + +typedef internal::AtomicWord ProtobufOnceType; -#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \ - pthread_once_t NAME = PTHREAD_ONCE_INIT +#define GOOGLE_PROTOBUF_ONCE_INIT ::google::protobuf::ONCE_STATE_UNINITIALIZED + +LIBPROTOBUF_EXPORT +void GoogleOnceInitImpl(ProtobufOnceType* once, Closure* closure); inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) { - pthread_once(once, init_func); + if (internal::Acquire_Load(once) != ONCE_STATE_DONE) { + internal::FunctionClosure0 func(init_func, false); + GoogleOnceInitImpl(once, &func); + } +} + +template +inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)(Arg*), + Arg* arg) { + if (internal::Acquire_Load(once) != ONCE_STATE_DONE) { + internal::FunctionClosure1 func(init_func, false, arg); + GoogleOnceInitImpl(once, &func); + } } -#endif +#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY + +class GoogleOnceDynamic { + public: + GoogleOnceDynamic() : state_(GOOGLE_PROTOBUF_ONCE_INIT) { } + + // If this->Init() has not been called before by any thread, + // execute (*func_with_arg)(arg) then return. + // Otherwise, wait until that prior invocation has finished + // executing its function, then return. + template + void Init(void (*func_with_arg)(T*), T* arg) { + GoogleOnceInit(&this->state_, + func_with_arg, + arg); + } + private: + ProtobufOnceType state_; +}; + +#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \ + ::google::protobuf::ProtobufOnceType NAME = GOOGLE_PROTOBUF_ONCE_INIT } // namespace protobuf } // namespace google -- cgit v1.1