aboutsummaryrefslogtreecommitdiffstats
path: root/src/google/protobuf/stubs/once.h
diff options
context:
space:
mode:
authorJeff Davidson <jpd@google.com>2014-09-15 16:29:06 -0700
committerJeff Davidson <jpd@google.com>2015-01-15 14:10:53 -0800
commita3b2a6da25a76f17c73d31def3952feb0fd2296e (patch)
tree586f7d5e9a7e05af45d0e821188097c0faa96219 /src/google/protobuf/stubs/once.h
parentc7c25812eb19d080087b71e08bfe35aff9f21433 (diff)
downloadexternal_protobuf-a3b2a6da25a76f17c73d31def3952feb0fd2296e.zip
external_protobuf-a3b2a6da25a76f17c73d31def3952feb0fd2296e.tar.gz
external_protobuf-a3b2a6da25a76f17c73d31def3952feb0fd2296e.tar.bz2
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
Diffstat (limited to 'src/google/protobuf/stubs/once.h')
-rw-r--r--src/google/protobuf/stubs/once.h101
1 files changed, 72 insertions, 29 deletions
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 <google/protobuf/stubs/atomicops.h>
#include <google/protobuf/stubs/common.h>
-#ifndef _WIN32
-#include <pthread.h>
-#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 <typename Arg>
+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 <typename Arg>
+inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)(Arg*),
+ Arg* arg) {
+ if (internal::Acquire_Load(once) != ONCE_STATE_DONE) {
+ internal::FunctionClosure1<Arg*> 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<typename T>
+ void Init(void (*func_with_arg)(T*), T* arg) {
+ GoogleOnceInit<T>(&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