aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Bo Yang <teboring@google.com>2015-04-24 15:34:40 -0700
committerGravatar Bo Yang <teboring@google.com>2015-04-24 18:09:55 -0700
commitd6c9f644ac62ec83196a75a47655a33a87875628 (patch)
tree742b0ab947ca26d5896c97e5909ca344bcc3ce3a /src
parentfe7b5667eb446766a1c2f30c691662a36f3df1f8 (diff)
internal changes
Change-Id: I66f216c70a19f44637090878d7e442d4d0f8991b
Diffstat (limited to 'src')
-rwxr-xr-xsrc/google/protobuf/arena.cc7
-rw-r--r--src/google/protobuf/arena.h5
-rw-r--r--src/google/protobuf/descriptor.h4
-rw-r--r--src/google/protobuf/preserve_unknown_enum_test.cc4
-rw-r--r--src/google/protobuf/repeated_field.h2
-rw-r--r--src/google/protobuf/stubs/atomicops_internals_pnacl.h176
-rw-r--r--src/google/protobuf/stubs/common.h42
-rwxr-xr-xsrc/google/protobuf/stubs/hash.h11
-rw-r--r--src/google/protobuf/stubs/platform_macros.h6
-rw-r--r--src/google/protobuf/stubs/type_traits.h4
10 files changed, 246 insertions, 15 deletions
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
index bda37413..f7059d26 100755
--- a/src/google/protobuf/arena.cc
+++ b/src/google/protobuf/arena.cc
@@ -29,6 +29,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <google/protobuf/arena.h>
+#include <google/protobuf/stubs/common.h>
#ifdef ADDRESS_SANITIZER
#include <sanitizer/asan_interface.h>
@@ -43,6 +44,12 @@ Arena::ThreadCache& Arena::thread_cache() {
static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL };
return thread_cache_;
}
+#elif defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE)
+Arena::ThreadCache& Arena::thread_cache() {
+ static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ =
+ new internal::ThreadLocalStorage<ThreadCache>();
+ return *thread_cache_->Get();
+}
#else
GOOGLE_THREAD_LOCAL Arena::ThreadCache Arena::thread_cache_ = { -1, NULL };
#endif
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
index bb15e80c..b48bef92 100644
--- a/src/google/protobuf/arena.h
+++ b/src/google/protobuf/arena.h
@@ -373,6 +373,11 @@ class LIBPROTOBUF_EXPORT Arena {
// Thread local variables cannot be exposed through DLL interface but we can
// wrap them in static functions.
static ThreadCache& thread_cache();
+#elif defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE)
+ // Android ndk does not support __thread keyword so we use a custom thread
+ // local storage class we implemented.
+ // iOS also does not support the __thread keyword.
+ static ThreadCache& thread_cache();
#else
static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
static ThreadCache& thread_cache() { return thread_cache_; }
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index 0e264f54..c0a48cea 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -59,6 +59,10 @@
#include <vector>
#include <google/protobuf/stubs/common.h>
+// TYPE_BOOL is defined in the MacOS's ConditionalMacros.h.
+#ifdef TYPE_BOOL
+#undef TYPE_BOOL
+#endif // TYPE_BOOL
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/preserve_unknown_enum_test.cc b/src/google/protobuf/preserve_unknown_enum_test.cc
index 9f8703ae..1673e8af 100644
--- a/src/google/protobuf/preserve_unknown_enum_test.cc
+++ b/src/google/protobuf/preserve_unknown_enum_test.cc
@@ -246,8 +246,6 @@ TEST(PreserveUnknownEnumTest, Proto2CatchesUnknownValues) {
protobuf_unittest::TestAllTypes message; // proto2 message
const google::protobuf::Reflection* r = message.GetReflection();
const google::protobuf::Descriptor* d = message.GetDescriptor();
- const google::protobuf::FieldDescriptor* singular_field =
- d->FindFieldByName("optional_nested_enum");
const google::protobuf::FieldDescriptor* repeated_field =
d->FindFieldByName("repeated_nested_enum");
// Add one element to the repeated field so that we can test
@@ -258,6 +256,8 @@ TEST(PreserveUnknownEnumTest, Proto2CatchesUnknownValues) {
r->AddEnum(&message, repeated_field, enum_value);
#ifdef PROTOBUF_HAS_DEATH_TEST
+ const google::protobuf::FieldDescriptor* singular_field =
+ d->FindFieldByName("optional_nested_enum");
// Enum-field integer-based setters GOOGLE_DCHECK-fail on invalid values, in order to
// remain consistent with proto2 generated code.
EXPECT_DEBUG_DEATH({
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index f5f5d3f4..7bfdc40a 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -626,7 +626,7 @@ DEFINE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(inline, MessageLite);
DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(Message);
-#undef DECLARE_SPECIALIZATIONS_FOR_BASE_CLASSES
+#undef DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES
template <>
inline const MessageLite& GenericTypeHandler<MessageLite>::default_instance() {
diff --git a/src/google/protobuf/stubs/atomicops_internals_pnacl.h b/src/google/protobuf/stubs/atomicops_internals_pnacl.h
index b10ac02c..3b314fd0 100644
--- a/src/google/protobuf/stubs/atomicops_internals_pnacl.h
+++ b/src/google/protobuf/stubs/atomicops_internals_pnacl.h
@@ -33,39 +33,197 @@
#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_
#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_
+#include <atomic>
+
namespace google {
namespace protobuf {
namespace internal {
+// This implementation is transitional and maintains the original API for
+// atomicops.h. This requires casting memory locations to the atomic types, and
+// assumes that the API and the C++11 implementation are layout-compatible,
+// which isn't true for all implementations or hardware platforms. The static
+// assertion should detect this issue, were it to fire then this header
+// shouldn't be used.
+//
+// TODO(jfb) If this header manages to stay committed then the API should be
+// modified, and all call sites updated.
+typedef volatile std::atomic<Atomic32>* AtomicLocation32;
+static_assert(sizeof(*(AtomicLocation32) nullptr) == sizeof(Atomic32),
+ "incompatible 32-bit atomic layout");
+
+inline void MemoryBarrier() {
+#if defined(__GLIBCXX__)
+ // Work around libstdc++ bug 51038 where atomic_thread_fence was declared but
+ // not defined, leading to the linker complaining about undefined references.
+ __atomic_thread_fence(std::memory_order_seq_cst);
+#else
+ std::atomic_thread_fence(std::memory_order_seq_cst);
+#endif
+}
+
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
- return __sync_val_compare_and_swap(ptr, old_value, new_value);
+ ((AtomicLocation32)ptr)
+ ->compare_exchange_strong(old_value,
+ new_value,
+ std::memory_order_relaxed,
+ std::memory_order_relaxed);
+ return old_value;
}
-inline void MemoryBarrier() {
- __sync_synchronize();
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+ Atomic32 new_value) {
+ return ((AtomicLocation32)ptr)
+ ->exchange(new_value, std::memory_order_relaxed);
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ return increment +
+ ((AtomicLocation32)ptr)
+ ->fetch_add(increment, std::memory_order_relaxed);
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ return increment + ((AtomicLocation32)ptr)->fetch_add(increment);
}
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
- Atomic32 ret = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+ ((AtomicLocation32)ptr)
+ ->compare_exchange_strong(old_value,
+ new_value,
+ std::memory_order_acquire,
+ std::memory_order_acquire);
+ return old_value;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+ Atomic32 old_value,
+ Atomic32 new_value) {
+ ((AtomicLocation32)ptr)
+ ->compare_exchange_strong(old_value,
+ new_value,
+ std::memory_order_release,
+ std::memory_order_relaxed);
+ return old_value;
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+ ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed);
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+ ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed);
MemoryBarrier();
- return ret;
}
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
- MemoryBarrier();
- *ptr = value;
+ ((AtomicLocation32)ptr)->store(value, std::memory_order_release);
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+ return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed);
}
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
- Atomic32 value = *ptr;
+ return ((AtomicLocation32)ptr)->load(std::memory_order_acquire);
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+ MemoryBarrier();
+ return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed);
+}
+
+#if defined(GOOGLE_PROTOBUF_ARCH_64_BIT)
+
+typedef volatile std::atomic<Atomic64>* AtomicLocation64;
+static_assert(sizeof(*(AtomicLocation64) nullptr) == sizeof(Atomic64),
+ "incompatible 64-bit atomic layout");
+
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+ Atomic64 old_value,
+ Atomic64 new_value) {
+ ((AtomicLocation64)ptr)
+ ->compare_exchange_strong(old_value,
+ new_value,
+ std::memory_order_relaxed,
+ std::memory_order_relaxed);
+ return old_value;
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+ Atomic64 new_value) {
+ return ((AtomicLocation64)ptr)
+ ->exchange(new_value, std::memory_order_relaxed);
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ return increment +
+ ((AtomicLocation64)ptr)
+ ->fetch_add(increment, std::memory_order_relaxed);
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ return increment + ((AtomicLocation64)ptr)->fetch_add(increment);
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+ Atomic64 old_value,
+ Atomic64 new_value) {
+ ((AtomicLocation64)ptr)
+ ->compare_exchange_strong(old_value,
+ new_value,
+ std::memory_order_acquire,
+ std::memory_order_acquire);
+ return old_value;
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+ Atomic64 old_value,
+ Atomic64 new_value) {
+ ((AtomicLocation64)ptr)
+ ->compare_exchange_strong(old_value,
+ new_value,
+ std::memory_order_release,
+ std::memory_order_relaxed);
+ return old_value;
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+ ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed);
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+ ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed);
MemoryBarrier();
- return value;
}
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+ ((AtomicLocation64)ptr)->store(value, std::memory_order_release);
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+ return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed);
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+ return ((AtomicLocation64)ptr)->load(std::memory_order_acquire);
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+ MemoryBarrier();
+ return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed);
+}
+
+#endif // defined(GOOGLE_PROTOBUF_ARCH_64_BIT)
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index c3f735a2..37123c7b 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -62,6 +62,14 @@
#include <exception>
#endif
+#if defined(__APPLE__)
+#include <TargetConditionals.h> // for TARGET_OS_IPHONE
+#endif
+
+#if defined(__ANDROID__) || defined(GOOGLE_PROTOBUF_OS_ANDROID) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || defined(GOOGLE_PROTOBUF_OS_IPHONE)
+#include <pthread.h>
+#endif
+
#if defined(_WIN32) && defined(GetMessage)
// Allow GetMessage to be used as a valid method name in protobuf classes.
// windows.h defines GetMessage() as a macro. Let's re-define it as an inline
@@ -157,7 +165,7 @@ std::string LIBPROTOBUF_EXPORT VersionString(int version);
typedef unsigned int uint;
#ifdef _MSC_VER
-typedef __int8 int8;
+typedef signed __int8 int8;
typedef __int16 int16;
typedef __int32 int32;
typedef __int64 int64;
@@ -1158,6 +1166,38 @@ class LIBPROTOBUF_EXPORT MutexLockMaybe {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe);
};
+#if defined(__ANDROID__) || defined(GOOGLE_PROTOBUF_OS_ANDROID) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || defined(GOOGLE_PROTOBUF_OS_IPHONE)
+// Android ndk does not support the __thread keyword very well yet. Here
+// we use pthread_key_create()/pthread_getspecific()/... methods for
+// TLS support on android.
+// iOS also does not support the __thread keyword.
+template<typename T>
+class ThreadLocalStorage {
+ public:
+ ThreadLocalStorage() {
+ pthread_key_create(&key_, &ThreadLocalStorage::Delete);
+ }
+ ~ThreadLocalStorage() {
+ pthread_key_delete(key_);
+ }
+ T* Get() {
+ T* result = static_cast<T*>(pthread_getspecific(key_));
+ if (result == NULL) {
+ result = new T();
+ pthread_setspecific(key_, result);
+ }
+ return result;
+ }
+ private:
+ static void Delete(void* value) {
+ delete static_cast<T*>(value);
+ }
+ pthread_key_t key_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadLocalStorage);
+};
+#endif
+
} // namespace internal
// We made these internal so that they would show up as such in the docs,
diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h
index 82d5052e..11bc2b37 100755
--- a/src/google/protobuf/stubs/hash.h
+++ b/src/google/protobuf/stubs/hash.h
@@ -172,6 +172,13 @@ struct hash<const char*> {
}
};
+template<>
+struct hash<bool> {
+ size_t operator()(bool x) const {
+ return static_cast<size_t>(x);
+ }
+};
+
template <typename Key, typename Data,
typename HashFcn = hash<Key>,
typename EqualKey = std::equal_to<Key>,
@@ -204,7 +211,7 @@ struct hash<string> {
static const size_t bucket_size = 4;
static const size_t min_buckets = 8;
- inline size_t operator()(const string& a, const string& b) const {
+ inline bool operator()(const string& a, const string& b) const {
return a < b;
}
};
@@ -222,7 +229,7 @@ struct hash<pair<First, Second> > {
static const size_t bucket_size = 4;
static const size_t min_buckets = 8;
- inline size_t operator()(const pair<First, Second>& a,
+ inline bool operator()(const pair<First, Second>& a,
const pair<First, Second>& b) const {
return a < b;
}
diff --git a/src/google/protobuf/stubs/platform_macros.h b/src/google/protobuf/stubs/platform_macros.h
index 1ff09b83..2ce7fc8f 100644
--- a/src/google/protobuf/stubs/platform_macros.h
+++ b/src/google/protobuf/stubs/platform_macros.h
@@ -95,12 +95,18 @@ GOOGLE_PROTOBUF_PLATFORM_ERROR
#if defined(__APPLE__)
#define GOOGLE_PROTOBUF_OS_APPLE
+#include <TargetConditionals.h>
+#if TARGET_OS_IPHONE
+#define GOOGLE_PROTOBUF_OS_IPHONE
+#endif
#elif defined(__native_client__)
#define GOOGLE_PROTOBUF_OS_NACL
#elif defined(sun)
#define GOOGLE_PROTOBUF_OS_SOLARIS
#elif defined(_AIX)
#define GOOGLE_PROTOBUF_OS_AIX
+#elif defined(__ANDROID__)
+#define GOOGLE_PROTOBUF_OS_ANDROID
#endif
#undef GOOGLE_PROTOBUF_PLATFORM_ERROR
diff --git a/src/google/protobuf/stubs/type_traits.h b/src/google/protobuf/stubs/type_traits.h
index b58cae3f..36a8f3b1 100644
--- a/src/google/protobuf/stubs/type_traits.h
+++ b/src/google/protobuf/stubs/type_traits.h
@@ -73,6 +73,10 @@ struct is_base_of {
typedef char (&yes)[1];
typedef char (&no)[2];
+ // BEGIN GOOGLE LOCAL MODIFICATION -- check is a #define on Mac.
+ #undef check
+ // END GOOGLE LOCAL MODIFICATION
+
static yes check(const B*);
static no check(const void*);