diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc index 2ce987cb2f..1853678140 100644 --- a/src/google/protobuf/arena.cc +++ b/src/google/protobuf/arena.cc @@ -38,7 +38,14 @@ namespace google { namespace protobuf { google::protobuf::internal::SequenceNumber Arena::lifecycle_id_generator_; +#ifdef PROTOBUF_USE_DLLS +Arena::ThreadCache& Arena::thread_cache() { + static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL }; + return thread_cache_; +} +#else GOOGLE_THREAD_LOCAL Arena::ThreadCache Arena::thread_cache_ = { -1, NULL }; +#endif void Arena::Init(const ArenaOptions& options) { lifecycle_id_ = lifecycle_id_generator_.GetNext(); @@ -130,18 +137,18 @@ void* Arena::AllocateAligned(size_t n) { // If this thread already owns a block in this arena then try to use that. // This fast path optimizes the case where multiple threads allocate from the // same arena. - if (thread_cache_.last_lifecycle_id_seen == lifecycle_id_ && - thread_cache_.last_block_used_ != NULL) { - if (thread_cache_.last_block_used_->avail() < n) { + if (thread_cache().last_lifecycle_id_seen == lifecycle_id_ && + thread_cache().last_block_used_ != NULL) { + if (thread_cache().last_block_used_->avail() < n) { return SlowAlloc(n); } - return AllocFromBlock(thread_cache_.last_block_used_, n); + return AllocFromBlock(thread_cache().last_block_used_, n); } // Check whether we own the last accessed block on this arena. // This fast path optimizes the case where a single thread uses multiple // arenas. - void* me = &thread_cache_; + void* me = &thread_cache(); Block* b = reinterpret_cast(google::protobuf::internal::Acquire_Load(&hint_)); if (!b || b->owner != me || b->avail() < n) { // If the next block to allocate from is the first block, try to claim it @@ -169,7 +176,7 @@ void* Arena::AllocFromBlock(Block* b, size_t n) { } void* Arena::SlowAlloc(size_t n) { - void* me = &thread_cache_; + void* me = &thread_cache(); Block* b = FindBlock(me); // Find block owned by me. // See if allocation fits in my latest block. if (b != NULL && b->avail() >= n) { diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index b5822bdbff..d0cb163c0a 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h @@ -312,7 +312,12 @@ class LIBPROTOBUF_EXPORT Arena { static const size_t kHeaderSize = sizeof(Block); static google::protobuf::internal::SequenceNumber lifecycle_id_generator_; +#ifdef PROTOBUF_USE_DLLS + static ThreadCache& thread_cache(); +#else static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_; + static ThreadCache& thread_cache() { return thread_cache_; } +#endif // SFINAE for skipping addition to delete list for a Type. This is mainly to // skip proto2/proto1 message objects with cc_enable_arenas=true from being @@ -434,8 +439,8 @@ class LIBPROTOBUF_EXPORT Arena { void CleanupList(); inline void SetThreadCacheBlock(Block* block) { - thread_cache_.last_block_used_ = block; - thread_cache_.last_lifecycle_id_seen = lifecycle_id_; + thread_cache().last_block_used_ = block; + thread_cache().last_lifecycle_id_seen = lifecycle_id_; } int64 lifecycle_id_; // Unique for each arena. Changes on Reset(). diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h index 2adad16a73..d829ed9191 100755 --- a/src/google/protobuf/arenastring.h +++ b/src/google/protobuf/arenastring.h @@ -53,7 +53,7 @@ namespace google { namespace protobuf { namespace internal { -struct ArenaStringPtr { +struct LIBPROTOBUF_EXPORT ArenaStringPtr { inline void Set(const ::std::string* default_value, const ::std::string& value, ::google::protobuf::Arena* arena) { if (ptr_ == default_value) { diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index 20fcfa62e0..2a04b2931b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -153,6 +153,7 @@ TEST(GeneratedMessageTest, Defaults) { &message.optional_import_message()); } +#ifndef PROTOBUF_USE_DLLS TEST(GeneratedMessageTest, Int32StringConversion) { EXPECT_EQ("971", Int32ToString(971)); EXPECT_EQ("(~0x7fffffff)", Int32ToString(kint32min)); @@ -165,6 +166,7 @@ TEST(GeneratedMessageTest, Int64StringConversion) { EXPECT_EQ("GOOGLE_LONGLONG(~0x7fffffffffffffff)", Int64ToString(kint64min)); EXPECT_EQ("GOOGLE_LONGLONG(9223372036854775807)", Int64ToString(kint64max)); } +#endif // !PROTOBUF_USE_DLLS TEST(GeneratedMessageTest, FloatingPointDefaults) { const unittest::TestExtremeDefaultValues& extreme_default = diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h index f6ae3e52ef..6d8a9d03fb 100644 --- a/src/google/protobuf/map.h +++ b/src/google/protobuf/map.h @@ -110,7 +110,7 @@ class Map { ~Map() { clear(); } // Iterators - class LIBPROTOBUF_EXPORT const_iterator + class const_iterator : public std::iterator { typedef typename hash_map::const_iterator InnerIt; @@ -139,7 +139,7 @@ class Map { InnerIt it_; }; - class LIBPROTOBUF_EXPORT iterator : public std::iterator { + class iterator : public std::iterator { typedef typename hash_map::iterator InnerIt; public: @@ -302,7 +302,7 @@ class Map { template - friend class LIBPROTOBUF_EXPORT internal::MapField; + friend class internal::MapField; }; } // namespace protobuf diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h index 4d3fcfb6f1..217b15f6a3 100644 --- a/src/google/protobuf/map_entry.h +++ b/src/google/protobuf/map_entry.h @@ -45,7 +45,7 @@ namespace internal { // Register all MapEntry default instances so we can delete them in // ShutdownProtobufLibrary(). -void RegisterMapEntryDefaultInstance(MessageLite* default_instance); +void LIBPROTOBUF_EXPORT RegisterMapEntryDefaultInstance(MessageLite* default_instance); // This is the common base class for MapEntry. It is used by MapFieldBase in // reflection api, in which the static type of key and value is unknown. @@ -84,7 +84,7 @@ class LIBPROTOBUF_EXPORT MapEntryBase : public Message { // Moreover, default_enum_value is used to initialize enum field in proto2. template -class LIBPROTOBUF_EXPORT MapEntry : public MapEntryBase { +class MapEntry : public MapEntryBase { // Handlers for key/value's proto field type. Used to infer internal layout // and provide parsing/serialization support. typedef MapProtoTypeHandler KeyProtoHandler; @@ -363,7 +363,7 @@ class LIBPROTOBUF_EXPORT MapEntry : public MapEntryBase { template - class LIBPROTOBUF_EXPORT MapEntryWrapper + class MapEntryWrapper : public MapEntry { typedef MapEntry - class LIBPROTOBUF_EXPORT MapEnumEntryWrapper + class MapEnumEntryWrapper : public MapEntry { typedef MapEntry - friend class LIBPROTOBUF_EXPORT internal::MapField; + friend class internal::MapField; friend class LIBPROTOBUF_EXPORT internal::GeneratedMessageReflection; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry); diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h index 0fad1351fd..8516d74eaa 100644 --- a/src/google/protobuf/map_field.h +++ b/src/google/protobuf/map_field.h @@ -137,7 +137,7 @@ class LIBPROTOBUF_EXPORT MapFieldBase { template -class LIBPROTOBUF_EXPORT MapField : public MapFieldBase { +class MapField : public MapFieldBase { // Handlers for key/value's proto field type. typedef MapProtoTypeHandler KeyProtoHandler; typedef MapProtoTypeHandler ValueProtoHandler; diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index 1d8f249977..a200bc9290 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -967,6 +967,7 @@ const RepeatedField& Reflection::GetRepeatedField( \ const Message& message, const FieldDescriptor* field) const; \ \ template<> \ +LIBPROTOBUF_EXPORT \ RepeatedField* Reflection::MutableRepeatedField( \ Message* message, const FieldDescriptor* field) const;