|
|
|
@ -37,9 +37,6 @@ |
|
|
|
|
#ifdef max |
|
|
|
|
#undef max // Visual Studio defines this macro
|
|
|
|
|
#endif |
|
|
|
|
#if LANG_CXX11 |
|
|
|
|
#include <google/protobuf/stubs/type_traits.h> |
|
|
|
|
#endif |
|
|
|
|
#if defined(_MSC_VER) && !defined(_LIBCPP_STD_VER) && !_HAS_EXCEPTIONS |
|
|
|
|
// Work around bugs in MSVC <typeinfo> header when _HAS_EXCEPTIONS=0.
|
|
|
|
|
#include <exception> |
|
|
|
@ -53,10 +50,13 @@ using type_info = ::type_info; |
|
|
|
|
|
|
|
|
|
#include <google/protobuf/arena_impl.h> |
|
|
|
|
#include <google/protobuf/stubs/port.h> |
|
|
|
|
#include <type_traits> |
|
|
|
|
|
|
|
|
|
namespace google { |
|
|
|
|
namespace protobuf { |
|
|
|
|
struct ArenaOptions; |
|
|
|
|
|
|
|
|
|
struct ArenaOptions; // defined below
|
|
|
|
|
|
|
|
|
|
} // namespace protobuf
|
|
|
|
|
|
|
|
|
|
namespace quality_webanswers { |
|
|
|
@ -66,27 +66,32 @@ void TempPrivateWorkAround(::google::protobuf::ArenaOptions* arena_options); |
|
|
|
|
} // namespace quality_webanswers
|
|
|
|
|
|
|
|
|
|
namespace protobuf { |
|
|
|
|
|
|
|
|
|
class Arena; // defined below
|
|
|
|
|
class Message; // defined in message.h
|
|
|
|
|
class MessageLite; |
|
|
|
|
|
|
|
|
|
namespace arena_metrics { |
|
|
|
|
|
|
|
|
|
void EnableArenaMetrics(::google::protobuf::ArenaOptions* options); |
|
|
|
|
|
|
|
|
|
} // namespace arena_metrics
|
|
|
|
|
|
|
|
|
|
class Arena; // defined below
|
|
|
|
|
class Message; // message.h
|
|
|
|
|
|
|
|
|
|
namespace internal { |
|
|
|
|
struct ArenaStringPtr; // arenastring.h
|
|
|
|
|
class LazyField; // lazy_field.h
|
|
|
|
|
|
|
|
|
|
template<typename Type> |
|
|
|
|
class GenericTypeHandler; // repeated_field.h
|
|
|
|
|
struct ArenaStringPtr; // defined in arenastring.h
|
|
|
|
|
class LazyField; // defined in lazy_field.h
|
|
|
|
|
|
|
|
|
|
template <typename Type> |
|
|
|
|
class GenericTypeHandler; // defined in repeated_field.h
|
|
|
|
|
|
|
|
|
|
// Templated cleanup methods.
|
|
|
|
|
template<typename T> void arena_destruct_object(void* object) { |
|
|
|
|
template <typename T> |
|
|
|
|
void arena_destruct_object(void* object) { |
|
|
|
|
reinterpret_cast<T*>(object)->~T(); |
|
|
|
|
} |
|
|
|
|
template<typename T> void arena_delete_object(void* object) { |
|
|
|
|
template <typename T> |
|
|
|
|
void arena_delete_object(void* object) { |
|
|
|
|
delete reinterpret_cast<T*>(object); |
|
|
|
|
} |
|
|
|
|
inline void arena_free(void* object, size_t size) { |
|
|
|
@ -285,70 +290,16 @@ class LIBPROTOBUF_EXPORT Arena { |
|
|
|
|
//
|
|
|
|
|
// This function also accepts any type T that satisfies the arena message
|
|
|
|
|
// allocation protocol, documented above.
|
|
|
|
|
#if LANG_CXX11 |
|
|
|
|
template <typename T, typename... Args> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateMessage( |
|
|
|
|
::google::protobuf::Arena* arena, Args&&... args) { |
|
|
|
|
Arena* arena, Args&&... args) { |
|
|
|
|
static_assert( |
|
|
|
|
InternalHelper<T>::is_arena_constructable::value, |
|
|
|
|
"CreateMessage can only construct types that are ArenaConstructable"); |
|
|
|
|
if (arena == NULL) { |
|
|
|
|
return new T(NULL, std::forward<Args>(args)...); |
|
|
|
|
} else { |
|
|
|
|
return arena->CreateMessageInternal<T>(std::forward<Args>(args)...); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static T* CreateMessage(::google::protobuf::Arena* arena) { |
|
|
|
|
#if LANG_CXX11 |
|
|
|
|
static_assert( |
|
|
|
|
InternalHelper<T>::is_arena_constructable::value, |
|
|
|
|
"CreateMessage can only construct types that are ArenaConstructable"); |
|
|
|
|
#endif |
|
|
|
|
if (arena == NULL) { |
|
|
|
|
return new T; |
|
|
|
|
} else { |
|
|
|
|
return arena->CreateMessageInternal<T>(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// One-argument form of CreateMessage. This is useful for constructing objects
|
|
|
|
|
// that implement the arena message construction protocol described above but
|
|
|
|
|
// take additional constructor arguments.
|
|
|
|
|
template <typename T, typename Arg> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static T* CreateMessage(::google::protobuf::Arena* arena, const Arg& arg) { |
|
|
|
|
#if LANG_CXX11 |
|
|
|
|
static_assert( |
|
|
|
|
InternalHelper<T>::is_arena_constructable::value, |
|
|
|
|
"CreateMessage can only construct types that are ArenaConstructable"); |
|
|
|
|
#endif |
|
|
|
|
if (arena == NULL) { |
|
|
|
|
return new T(NULL, arg); |
|
|
|
|
} else { |
|
|
|
|
return arena->CreateMessageInternal<T>(arg); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Two-argument form of CreateMessage. This is useful for constructing objects
|
|
|
|
|
// that implement the arena message construction protocol described above but
|
|
|
|
|
// take additional constructor arguments.
|
|
|
|
|
template <typename T, typename Arg1, typename Arg2> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static T* CreateMessage(::google::protobuf::Arena* arena, |
|
|
|
|
const Arg1& arg1, |
|
|
|
|
const Arg2& arg2) { |
|
|
|
|
#if LANG_CXX11 |
|
|
|
|
static_assert( |
|
|
|
|
InternalHelper<T>::is_arena_constructable::value, |
|
|
|
|
"CreateMessage can only construct types that are ArenaConstructable"); |
|
|
|
|
#endif |
|
|
|
|
if (arena == NULL) { |
|
|
|
|
return new T(NULL, arg1, arg2); |
|
|
|
|
} else { |
|
|
|
|
return arena->CreateMessageInternal<T>(arg1, arg2); |
|
|
|
|
} |
|
|
|
|
// We must delegate to CreateMaybeMessage() and NOT CreateMessageInternal()
|
|
|
|
|
// because protobuf generated classes specialize CreateMaybeMessage() and we
|
|
|
|
|
// need to use that specialization for code size reasons.
|
|
|
|
|
return Arena::CreateMaybeMessage<T>(arena, std::forward<Args>(args)...); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// API to create any objects on the arena. Note that only the object will
|
|
|
|
@ -366,154 +317,12 @@ class LIBPROTOBUF_EXPORT Arena { |
|
|
|
|
// (unless the destructor is trivial). Hence, from T's point of view, it is as
|
|
|
|
|
// if the object were allocated on the heap (except that the underlying memory
|
|
|
|
|
// is obtained from the arena).
|
|
|
|
|
#if LANG_CXX11 |
|
|
|
|
template <typename T, typename... Args> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static T* Create(::google::protobuf::Arena* arena, Args&&... args) { |
|
|
|
|
if (arena == NULL) { |
|
|
|
|
return new T(std::forward<Args>(args)...); |
|
|
|
|
} else { |
|
|
|
|
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value, |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* Create(Arena* arena, |
|
|
|
|
Args&&... args) { |
|
|
|
|
return CreateNoMessage<T>(arena, is_arena_constructable<T>(), |
|
|
|
|
std::forward<Args>(args)...); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static T* Create(::google::protobuf::Arena* arena) { |
|
|
|
|
if (arena == NULL) { |
|
|
|
|
return new T(); |
|
|
|
|
} else { |
|
|
|
|
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Version of the above with one constructor argument for the created object.
|
|
|
|
|
template <typename T, typename Arg> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static T* Create(::google::protobuf::Arena* arena, const Arg& arg) { |
|
|
|
|
if (arena == NULL) { |
|
|
|
|
return new T(arg); |
|
|
|
|
} else { |
|
|
|
|
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value, |
|
|
|
|
arg); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Version of the above with two constructor arguments for the created object.
|
|
|
|
|
template <typename T, typename Arg1, typename Arg2> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static T* Create(::google::protobuf::Arena* arena, const Arg1& arg1, const Arg2& arg2) { |
|
|
|
|
if (arena == NULL) { |
|
|
|
|
return new T(arg1, arg2); |
|
|
|
|
} else { |
|
|
|
|
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value, |
|
|
|
|
arg1, arg2); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Version of the above with three constructor arguments for the created
|
|
|
|
|
// object.
|
|
|
|
|
template <typename T, typename Arg1, typename Arg2, typename Arg3> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static T* Create(::google::protobuf::Arena* arena, |
|
|
|
|
const Arg1& arg1, |
|
|
|
|
const Arg2& arg2, |
|
|
|
|
const Arg3& arg3) { |
|
|
|
|
if (arena == NULL) { |
|
|
|
|
return new T(arg1, arg2, arg3); |
|
|
|
|
} else { |
|
|
|
|
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value, |
|
|
|
|
arg1, arg2, arg3); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Version of the above with four constructor arguments for the created
|
|
|
|
|
// object.
|
|
|
|
|
template <typename T, typename Arg1, typename Arg2, typename Arg3, |
|
|
|
|
typename Arg4> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static T* Create(::google::protobuf::Arena* arena, |
|
|
|
|
const Arg1& arg1, const Arg2& arg2, |
|
|
|
|
const Arg3& arg3, const Arg4& arg4) { |
|
|
|
|
if (arena == NULL) { |
|
|
|
|
return new T(arg1, arg2, arg3, arg4); |
|
|
|
|
} else { |
|
|
|
|
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value, |
|
|
|
|
arg1, arg2, arg3, arg4); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Version of the above with five constructor arguments for the created
|
|
|
|
|
// object.
|
|
|
|
|
template <typename T, typename Arg1, typename Arg2, typename Arg3, |
|
|
|
|
typename Arg4, typename Arg5> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static T* Create(::google::protobuf::Arena* arena, |
|
|
|
|
const Arg1& arg1, const Arg2& arg2, |
|
|
|
|
const Arg3& arg3, const Arg4& arg4, |
|
|
|
|
const Arg5& arg5) { |
|
|
|
|
if (arena == NULL) { |
|
|
|
|
return new T(arg1, arg2, arg3, arg4, arg5); |
|
|
|
|
} else { |
|
|
|
|
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value, |
|
|
|
|
arg1, arg2, arg3, arg4, arg5); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Version of the above with six constructor arguments for the created
|
|
|
|
|
// object.
|
|
|
|
|
template <typename T, typename Arg1, typename Arg2, typename Arg3, |
|
|
|
|
typename Arg4, typename Arg5, typename Arg6> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static T* Create(::google::protobuf::Arena* arena, |
|
|
|
|
const Arg1& arg1, const Arg2& arg2, |
|
|
|
|
const Arg3& arg3, const Arg4& arg4, |
|
|
|
|
const Arg5& arg5, const Arg6& arg6) { |
|
|
|
|
if (arena == NULL) { |
|
|
|
|
return new T(arg1, arg2, arg3, arg4, arg5, arg6); |
|
|
|
|
} else { |
|
|
|
|
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value, |
|
|
|
|
arg1, arg2, arg3, arg4, arg5, arg6); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Version of the above with seven constructor arguments for the created
|
|
|
|
|
// object.
|
|
|
|
|
template <typename T, typename Arg1, typename Arg2, typename Arg3, |
|
|
|
|
typename Arg4, typename Arg5, typename Arg6, typename Arg7> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static T* Create(::google::protobuf::Arena* arena, |
|
|
|
|
const Arg1& arg1, const Arg2& arg2, |
|
|
|
|
const Arg3& arg3, const Arg4& arg4, |
|
|
|
|
const Arg5& arg5, const Arg6& arg6, |
|
|
|
|
const Arg7& arg7) { |
|
|
|
|
if (arena == NULL) { |
|
|
|
|
return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7); |
|
|
|
|
} else { |
|
|
|
|
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value, |
|
|
|
|
arg1, arg2, arg3, arg4, arg5, arg6, arg7); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Version of the above with eight constructor arguments for the created
|
|
|
|
|
// object.
|
|
|
|
|
template <typename T, typename Arg1, typename Arg2, typename Arg3, |
|
|
|
|
typename Arg4, typename Arg5, typename Arg6, typename Arg7, |
|
|
|
|
typename Arg8> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static T* Create(::google::protobuf::Arena* arena, |
|
|
|
|
const Arg1& arg1, const Arg2& arg2, |
|
|
|
|
const Arg3& arg3, const Arg4& arg4, |
|
|
|
|
const Arg5& arg5, const Arg6& arg6, |
|
|
|
|
const Arg7& arg7, const Arg8& arg8) { |
|
|
|
|
if (arena == NULL) { |
|
|
|
|
return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); |
|
|
|
|
} else { |
|
|
|
|
return arena->CreateInternal<T>( |
|
|
|
|
google::protobuf::internal::has_trivial_destructor<T>::value, |
|
|
|
|
arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Create an array of object type T on the arena *without* invoking the
|
|
|
|
|
// constructor of T. If `arena` is null, then the return value should be freed
|
|
|
|
@ -521,10 +330,14 @@ class LIBPROTOBUF_EXPORT Arena { |
|
|
|
|
// To ensure safe uses, this function checks at compile time
|
|
|
|
|
// (when compiled as C++11) that T is trivially default-constructible and
|
|
|
|
|
// trivially destructible.
|
|
|
|
|
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static T* CreateArray(::google::protobuf::Arena* arena, size_t num_elements) { |
|
|
|
|
GOOGLE_CHECK_LE(num_elements, |
|
|
|
|
std::numeric_limits<size_t>::max() / sizeof(T)) |
|
|
|
|
template <typename T> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateArray( |
|
|
|
|
Arena* arena, size_t num_elements) { |
|
|
|
|
static_assert(std::is_pod<T>::value, |
|
|
|
|
"CreateArray requires a trivially constructible type"); |
|
|
|
|
static_assert(std::is_trivially_destructible<T>::value, |
|
|
|
|
"CreateArray requires a trivially destructible type"); |
|
|
|
|
GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T)) |
|
|
|
|
<< "Requested size is too large to fit into size_t."; |
|
|
|
|
if (arena == NULL) { |
|
|
|
|
return static_cast<T*>(::operator new[](num_elements * sizeof(T))); |
|
|
|
@ -566,9 +379,9 @@ class LIBPROTOBUF_EXPORT Arena { |
|
|
|
|
|
|
|
|
|
// Adds |object| to a list of heap-allocated objects to be freed with |delete|
|
|
|
|
|
// when the arena is destroyed or reset.
|
|
|
|
|
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE |
|
|
|
|
void Own(T* object) { |
|
|
|
|
OwnInternal(object, google::protobuf::internal::is_convertible<T*, ::google::protobuf::Message*>()); |
|
|
|
|
template <typename T> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE void Own(T* object) { |
|
|
|
|
OwnInternal(object, std::is_convertible<T*, Message*>()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Adds |object| to a list of objects whose destructors will be manually
|
|
|
|
@ -576,8 +389,8 @@ class LIBPROTOBUF_EXPORT Arena { |
|
|
|
|
// that it does not free the underlying memory with |delete|; hence, it is
|
|
|
|
|
// normally only used for objects that are placement-newed into
|
|
|
|
|
// arena-allocated memory.
|
|
|
|
|
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE |
|
|
|
|
void OwnDestructor(T* object) { |
|
|
|
|
template <typename T> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE void OwnDestructor(T* object) { |
|
|
|
|
if (object != NULL) { |
|
|
|
|
impl_.AddCleanup(object, &internal::arena_destruct_object<T>); |
|
|
|
|
} |
|
|
|
@ -596,8 +409,9 @@ class LIBPROTOBUF_EXPORT Arena { |
|
|
|
|
// message, or NULL otherwise. This differs from value->GetArena() in that the
|
|
|
|
|
// latter is a virtual call, while this method is a templated call that
|
|
|
|
|
// resolves at compile-time.
|
|
|
|
|
template<typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static ::google::protobuf::Arena* GetArena(const T* value) { |
|
|
|
|
template <typename T> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static Arena* GetArena( |
|
|
|
|
const T* value) { |
|
|
|
|
return GetArenaInternal(value, is_arena_constructable<T>()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -608,80 +422,89 @@ class LIBPROTOBUF_EXPORT Arena { |
|
|
|
|
template <typename U> |
|
|
|
|
static double DestructorSkippable(...); |
|
|
|
|
|
|
|
|
|
typedef google::protobuf::internal::integral_constant< |
|
|
|
|
typedef std::integral_constant< |
|
|
|
|
bool, sizeof(DestructorSkippable<T>(static_cast<const T*>(0))) == |
|
|
|
|
sizeof(char) || |
|
|
|
|
google::protobuf::internal::has_trivial_destructor<T>::value> |
|
|
|
|
std::is_trivially_destructible<T>::value> |
|
|
|
|
is_destructor_skippable; |
|
|
|
|
|
|
|
|
|
template<typename U> |
|
|
|
|
template <typename U> |
|
|
|
|
static char ArenaConstructable( |
|
|
|
|
const typename U::InternalArenaConstructable_*); |
|
|
|
|
template<typename U> |
|
|
|
|
template <typename U> |
|
|
|
|
static double ArenaConstructable(...); |
|
|
|
|
|
|
|
|
|
typedef google::protobuf::internal::integral_constant<bool, sizeof(ArenaConstructable<T>( |
|
|
|
|
typedef std::integral_constant<bool, sizeof(ArenaConstructable<T>( |
|
|
|
|
static_cast<const T*>(0))) == |
|
|
|
|
sizeof(char)> |
|
|
|
|
is_arena_constructable; |
|
|
|
|
|
|
|
|
|
#if LANG_CXX11 |
|
|
|
|
template <typename... Args> |
|
|
|
|
static T* Construct(void* ptr, Args&&... args) { |
|
|
|
|
return new (ptr) T(std::forward<Args>(args)...); |
|
|
|
|
} |
|
|
|
|
#else |
|
|
|
|
template <typename Arg1> |
|
|
|
|
static T* Construct(void* ptr, const Arg1& arg1) { |
|
|
|
|
return new (ptr) T(arg1); |
|
|
|
|
} |
|
|
|
|
template <typename Arg1, typename Arg2> |
|
|
|
|
static T* Construct(void* ptr, const Arg1& arg1, const Arg2& arg2) { |
|
|
|
|
return new (ptr) T(arg1, arg2); |
|
|
|
|
} |
|
|
|
|
template <typename Arg1, typename Arg2, typename Arg3> |
|
|
|
|
static T* Construct(void* ptr, const Arg1& arg1, |
|
|
|
|
const Arg2& arg2, const Arg3& arg3) { |
|
|
|
|
return new (ptr) T(arg1, arg2, arg3); |
|
|
|
|
} |
|
|
|
|
#endif // LANG_CXX11
|
|
|
|
|
|
|
|
|
|
static Arena* GetArena(const T* p) { return p->GetArenaNoVirtual(); } |
|
|
|
|
|
|
|
|
|
friend class Arena; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// Helper typetrait that indicates support for arenas in a type T at compile
|
|
|
|
|
// Helper typetraits that indicates support for arenas in a type T at compile
|
|
|
|
|
// time. This is public only to allow construction of higher-level templated
|
|
|
|
|
// utilities. is_arena_constructable<T>::value is true if the message type T
|
|
|
|
|
// has arena support enabled, and false otherwise.
|
|
|
|
|
// utilities.
|
|
|
|
|
//
|
|
|
|
|
// is_arena_constructable<T>::value is true if the message type T has arena
|
|
|
|
|
// support enabled, and false otherwise.
|
|
|
|
|
//
|
|
|
|
|
// is_destructor_skippable<T>::value is true if the message type T has told
|
|
|
|
|
// the arena that it is safe to skip the destructor, and false otherwise.
|
|
|
|
|
//
|
|
|
|
|
// This is inside Arena because only Arena has the friend relationships
|
|
|
|
|
// necessary to see the underlying generated code traits.
|
|
|
|
|
template <typename T> |
|
|
|
|
struct is_arena_constructable : InternalHelper<T>::is_arena_constructable {}; |
|
|
|
|
template <typename T> |
|
|
|
|
struct is_destructor_skippable : InternalHelper<T>::is_destructor_skippable { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static T* CreateMessageInternal(::google::protobuf::Arena* arena) { |
|
|
|
|
#if LANG_CXX11 |
|
|
|
|
template <typename T, typename... Args> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateMessageInternal( |
|
|
|
|
Arena* arena, Args&&... args) { |
|
|
|
|
static_assert( |
|
|
|
|
InternalHelper<T>::is_arena_constructable::value, |
|
|
|
|
"CreateMessage can only construct types that are ArenaConstructable"); |
|
|
|
|
#endif |
|
|
|
|
if (arena == NULL) { |
|
|
|
|
return new T; |
|
|
|
|
return new T(nullptr, std::forward<Args>(args)...); |
|
|
|
|
} else { |
|
|
|
|
return arena->CreateMessageInternal<T>(); |
|
|
|
|
return arena->DoCreateMessage<T>(std::forward<Args>(args)...); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static T* CreateInternal(::google::protobuf::Arena* arena) { |
|
|
|
|
// This specialization for no arguments is necessary, because its behavior is
|
|
|
|
|
// slightly different. When the arena pointer is nullptr, it calls T()
|
|
|
|
|
// instead of T(nullptr).
|
|
|
|
|
template <typename T> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateMessageInternal( |
|
|
|
|
Arena* arena) { |
|
|
|
|
static_assert( |
|
|
|
|
InternalHelper<T>::is_arena_constructable::value, |
|
|
|
|
"CreateMessage can only construct types that are ArenaConstructable"); |
|
|
|
|
if (arena == NULL) { |
|
|
|
|
return new T(); |
|
|
|
|
} else { |
|
|
|
|
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value); |
|
|
|
|
return arena->DoCreateMessage<T>(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T, typename... Args> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateInternal( |
|
|
|
|
Arena* arena, Args&&... args) { |
|
|
|
|
if (arena == NULL) { |
|
|
|
|
return new T(std::forward<Args>(args)...); |
|
|
|
|
} else { |
|
|
|
|
return arena->DoCreate<T>(std::is_trivially_destructible<T>::value, |
|
|
|
|
std::forward<Args>(args)...); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -696,8 +519,9 @@ class LIBPROTOBUF_EXPORT Arena { |
|
|
|
|
// Allocate and also optionally call on_arena_allocation callback with the
|
|
|
|
|
// allocated type info when the hooks are in place in ArenaOptions and
|
|
|
|
|
// the cookie is not null.
|
|
|
|
|
template<typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
void* AllocateInternal(bool skip_explicit_ownership) { |
|
|
|
|
template <typename T> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void* AllocateInternal( |
|
|
|
|
bool skip_explicit_ownership) { |
|
|
|
|
const size_t n = internal::AlignUpTo8(sizeof(T)); |
|
|
|
|
AllocHook(RTTI_TYPE_ID(T), n); |
|
|
|
|
// Monitor allocation if needed.
|
|
|
|
@ -714,27 +538,49 @@ class LIBPROTOBUF_EXPORT Arena { |
|
|
|
|
// as it can cause confusing API usages, and end up having double free in
|
|
|
|
|
// user code. These are used only internally from LazyField and Repeated
|
|
|
|
|
// fields, since they are designed to work in all mode combinations.
|
|
|
|
|
template <typename Msg> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static Msg* CreateMaybeMessage(Arena* arena, google::protobuf::internal::true_type) { |
|
|
|
|
return CreateMessageInternal<Msg>(arena); |
|
|
|
|
template <typename Msg, typename... Args> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static Msg* DoCreateMaybeMessage( |
|
|
|
|
Arena* arena, std::true_type, Args&&... args) { |
|
|
|
|
return CreateMessageInternal<Msg>(arena, std::forward<Args>(args)...); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static T* CreateMaybeMessage(Arena* arena, google::protobuf::internal::false_type) { |
|
|
|
|
return CreateInternal<T>(arena); |
|
|
|
|
template <typename T, typename... Args> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* DoCreateMaybeMessage( |
|
|
|
|
Arena* arena, std::false_type, Args&&... args) { |
|
|
|
|
return CreateInternal<T>(arena, std::forward<Args>(args)...); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static T* CreateMaybeMessage(Arena* arena) { |
|
|
|
|
return CreateMaybeMessage<T>(arena, is_arena_constructable<T>()); |
|
|
|
|
template <typename T, typename... Args> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateMaybeMessage( |
|
|
|
|
Arena* arena, Args&&... args) { |
|
|
|
|
return DoCreateMaybeMessage<T>(arena, is_arena_constructable<T>(), |
|
|
|
|
std::forward<Args>(args)...); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T, typename... Args> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateNoMessage( |
|
|
|
|
Arena* arena, std::true_type, Args&&... args) { |
|
|
|
|
// User is constructing with Create() despite the fact that T supports arena
|
|
|
|
|
// construction. In this case we have to delegate to CreateInternal(), and
|
|
|
|
|
// we can't use any CreateMaybeMessage() specialization that may be defined.
|
|
|
|
|
return CreateInternal<T>(arena, std::forward<Args>(args)...); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T, typename... Args> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateNoMessage( |
|
|
|
|
Arena* arena, std::false_type, Args&&... args) { |
|
|
|
|
// User is constructing with Create() and the type does not support arena
|
|
|
|
|
// construction. In this case we can delegate to CreateMaybeMessage() and
|
|
|
|
|
// use any specialization that may be available for that.
|
|
|
|
|
return CreateMaybeMessage<T>(arena, std::forward<Args>(args)...); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Just allocate the required size for the given type assuming the
|
|
|
|
|
// type has a trivial constructor.
|
|
|
|
|
template<typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
T* CreateInternalRawArray(size_t num_elements) { |
|
|
|
|
GOOGLE_CHECK_LE(num_elements, |
|
|
|
|
std::numeric_limits<size_t>::max() / sizeof(T)) |
|
|
|
|
template <typename T> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T* CreateInternalRawArray( |
|
|
|
|
size_t num_elements) { |
|
|
|
|
GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T)) |
|
|
|
|
<< "Requested size is too large to fit into size_t."; |
|
|
|
|
const size_t n = internal::AlignUpTo8(sizeof(T) * num_elements); |
|
|
|
|
// Monitor allocation if needed.
|
|
|
|
@ -742,143 +588,18 @@ class LIBPROTOBUF_EXPORT Arena { |
|
|
|
|
return static_cast<T*>(impl_.AllocateAligned(n)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#if LANG_CXX11 |
|
|
|
|
template <typename T, typename... Args> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
T* CreateInternal(bool skip_explicit_ownership, Args&&... args) { |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T* DoCreate( |
|
|
|
|
bool skip_explicit_ownership, Args&&... args) { |
|
|
|
|
return new (AllocateInternal<T>(skip_explicit_ownership)) |
|
|
|
|
T(std::forward<Args>(args)...); |
|
|
|
|
} |
|
|
|
|
#else |
|
|
|
|
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
T* CreateInternal(bool skip_explicit_ownership) { |
|
|
|
|
return new (AllocateInternal<T>(skip_explicit_ownership)) T(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T, typename Arg> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
T* CreateInternal(bool skip_explicit_ownership, const Arg& arg) { |
|
|
|
|
return new (AllocateInternal<T>(skip_explicit_ownership)) T(arg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T, typename Arg1, typename Arg2> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
T* CreateInternal(bool skip_explicit_ownership, |
|
|
|
|
const Arg1& arg1, |
|
|
|
|
const Arg2& arg2) { |
|
|
|
|
return new (AllocateInternal<T>(skip_explicit_ownership)) T(arg1, arg2); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T, typename Arg1, typename Arg2, typename Arg3> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
T* CreateInternal(bool skip_explicit_ownership, |
|
|
|
|
const Arg1& arg1, |
|
|
|
|
const Arg2& arg2, |
|
|
|
|
const Arg3& arg3) { |
|
|
|
|
return new (AllocateInternal<T>(skip_explicit_ownership)) |
|
|
|
|
T(arg1, arg2, arg3); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T, typename Arg1, typename Arg2, typename Arg3, |
|
|
|
|
typename Arg4> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
T* CreateInternal(bool skip_explicit_ownership, |
|
|
|
|
const Arg1& arg1, |
|
|
|
|
const Arg2& arg2, |
|
|
|
|
const Arg3& arg3, |
|
|
|
|
const Arg4& arg4) { |
|
|
|
|
return new (AllocateInternal<T>(skip_explicit_ownership)) |
|
|
|
|
T(arg1, arg2, arg3, arg4); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T, typename Arg1, typename Arg2, typename Arg3, |
|
|
|
|
typename Arg4, typename Arg5> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
T* CreateInternal(bool skip_explicit_ownership, |
|
|
|
|
const Arg1& arg1, |
|
|
|
|
const Arg2& arg2, |
|
|
|
|
const Arg3& arg3, |
|
|
|
|
const Arg4& arg4, |
|
|
|
|
const Arg5& arg5) { |
|
|
|
|
return new (AllocateInternal<T>(skip_explicit_ownership)) |
|
|
|
|
T(arg1, arg2, arg3, arg4, arg5); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T, typename Arg1, typename Arg2, typename Arg3, |
|
|
|
|
typename Arg4, typename Arg5, typename Arg6> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
T* CreateInternal(bool skip_explicit_ownership, |
|
|
|
|
const Arg1& arg1, |
|
|
|
|
const Arg2& arg2, |
|
|
|
|
const Arg3& arg3, |
|
|
|
|
const Arg4& arg4, |
|
|
|
|
const Arg5& arg5, |
|
|
|
|
const Arg6& arg6) { |
|
|
|
|
return new (AllocateInternal<T>(skip_explicit_ownership)) |
|
|
|
|
T(arg1, arg2, arg3, arg4, arg5, arg6); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T, typename Arg1, typename Arg2, typename Arg3, |
|
|
|
|
typename Arg4, typename Arg5, typename Arg6, typename Arg7> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
T* CreateInternal(bool skip_explicit_ownership, |
|
|
|
|
const Arg1& arg1, |
|
|
|
|
const Arg2& arg2, |
|
|
|
|
const Arg3& arg3, |
|
|
|
|
const Arg4& arg4, |
|
|
|
|
const Arg5& arg5, |
|
|
|
|
const Arg6& arg6, |
|
|
|
|
const Arg7& arg7) { |
|
|
|
|
return new (AllocateInternal<T>(skip_explicit_ownership)) |
|
|
|
|
T(arg1, arg2, arg3, arg4, arg5, arg6, arg7); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T, typename Arg1, typename Arg2, typename Arg3, |
|
|
|
|
typename Arg4, typename Arg5, typename Arg6, typename Arg7, |
|
|
|
|
typename Arg8> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
T* CreateInternal(bool skip_explicit_ownership, |
|
|
|
|
const Arg1& arg1, |
|
|
|
|
const Arg2& arg2, |
|
|
|
|
const Arg3& arg3, |
|
|
|
|
const Arg4& arg4, |
|
|
|
|
const Arg5& arg5, |
|
|
|
|
const Arg6& arg6, |
|
|
|
|
const Arg7& arg7, |
|
|
|
|
const Arg8& arg8) { |
|
|
|
|
return new (AllocateInternal<T>(skip_explicit_ownership)) |
|
|
|
|
T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
#if LANG_CXX11 |
|
|
|
|
template <typename T, typename... Args> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T* CreateMessageInternal( |
|
|
|
|
Args&&... args) { |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T* DoCreateMessage(Args&&... args) { |
|
|
|
|
return InternalHelper<T>::Construct( |
|
|
|
|
AllocateInternal<T>(InternalHelper<T>::is_destructor_skippable::value), |
|
|
|
|
this, std::forward<Args>(args)...); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
template <typename T> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T* CreateMessageInternal() { |
|
|
|
|
return InternalHelper<T>::Construct( |
|
|
|
|
AllocateInternal<T>(InternalHelper<T>::is_destructor_skippable::value), |
|
|
|
|
this); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T, typename Arg> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
T* CreateMessageInternal(const Arg& arg) { |
|
|
|
|
return InternalHelper<T>::Construct( |
|
|
|
|
AllocateInternal<T>(InternalHelper<T>::is_destructor_skippable::value), |
|
|
|
|
this, arg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T, typename Arg1, typename Arg2> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
T* CreateMessageInternal(const Arg1& arg1, const Arg2& arg2) { |
|
|
|
|
return InternalHelper<T>::Construct( |
|
|
|
|
AllocateInternal<T>(InternalHelper<T>::is_destructor_skippable::value), |
|
|
|
|
this, arg1, arg2); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// CreateInArenaStorage is used to implement map field. Without it,
|
|
|
|
|
// google::protobuf::Map need to call generated message's protected arena constructor,
|
|
|
|
@ -893,22 +614,22 @@ class LIBPROTOBUF_EXPORT Arena { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T> |
|
|
|
|
static void CreateInArenaStorageInternal( |
|
|
|
|
T* ptr, Arena* arena, google::protobuf::internal::true_type) { |
|
|
|
|
static void CreateInArenaStorageInternal(T* ptr, Arena* arena, |
|
|
|
|
std::true_type) { |
|
|
|
|
InternalHelper<T>::Construct(ptr, arena); |
|
|
|
|
} |
|
|
|
|
template <typename T> |
|
|
|
|
static void CreateInArenaStorageInternal( |
|
|
|
|
T* ptr, Arena* /* arena */, google::protobuf::internal::false_type) { |
|
|
|
|
static void CreateInArenaStorageInternal(T* ptr, Arena* /* arena */, |
|
|
|
|
std::false_type) { |
|
|
|
|
new (ptr) T(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T> |
|
|
|
|
static void RegisterDestructorInternal( |
|
|
|
|
T* /* ptr */, Arena* /* arena */, google::protobuf::internal::true_type) {} |
|
|
|
|
static void RegisterDestructorInternal(T* /* ptr */, Arena* /* arena */, |
|
|
|
|
std::true_type) {} |
|
|
|
|
template <typename T> |
|
|
|
|
static void RegisterDestructorInternal( |
|
|
|
|
T* ptr, Arena* arena, google::protobuf::internal::false_type) { |
|
|
|
|
static void RegisterDestructorInternal(T* ptr, Arena* arena, |
|
|
|
|
std::false_type) { |
|
|
|
|
arena->OwnDestructor(ptr); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -917,15 +638,16 @@ class LIBPROTOBUF_EXPORT Arena { |
|
|
|
|
// is a subtype of ::google::protobuf::Message and 'false_type' otherwise. Collapsing
|
|
|
|
|
// all template instantiations to one for generic Message reduces code size,
|
|
|
|
|
// using the virtual destructor instead.
|
|
|
|
|
template<typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
void OwnInternal(T* object, google::protobuf::internal::true_type) { |
|
|
|
|
template <typename T> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void OwnInternal(T* object, |
|
|
|
|
std::true_type) { |
|
|
|
|
if (object != NULL) { |
|
|
|
|
impl_.AddCleanup(object, |
|
|
|
|
&internal::arena_delete_object< ::google::protobuf::Message>); |
|
|
|
|
impl_.AddCleanup(object, &internal::arena_delete_object<Message>); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
template<typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
void OwnInternal(T* object, google::protobuf::internal::false_type) { |
|
|
|
|
template <typename T> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void OwnInternal(T* object, |
|
|
|
|
std::false_type) { |
|
|
|
|
if (object != NULL) { |
|
|
|
|
impl_.AddCleanup(object, &internal::arena_delete_object<T>); |
|
|
|
|
} |
|
|
|
@ -934,16 +656,15 @@ class LIBPROTOBUF_EXPORT Arena { |
|
|
|
|
// Implementation for GetArena(). Only message objects with
|
|
|
|
|
// InternalArenaConstructable_ tags can be associated with an arena, and such
|
|
|
|
|
// objects must implement a GetArenaNoVirtual() method.
|
|
|
|
|
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static ::google::protobuf::Arena* GetArenaInternal( |
|
|
|
|
const T* value, google::protobuf::internal::true_type) { |
|
|
|
|
template <typename T> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static Arena* GetArenaInternal( |
|
|
|
|
const T* value, std::true_type) { |
|
|
|
|
return InternalHelper<T>::GetArena(value); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T> |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE |
|
|
|
|
static ::google::protobuf::Arena* GetArenaInternal( |
|
|
|
|
const T* /* value */, google::protobuf::internal::false_type) { |
|
|
|
|
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static Arena* GetArenaInternal( |
|
|
|
|
const T* /* value */, std::false_type) { |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -965,9 +686,10 @@ class LIBPROTOBUF_EXPORT Arena { |
|
|
|
|
void* hooks_cookie_; |
|
|
|
|
|
|
|
|
|
template <typename Type> |
|
|
|
|
friend class ::google::protobuf::internal::GenericTypeHandler; |
|
|
|
|
friend class internal::GenericTypeHandler; |
|
|
|
|
friend struct internal::ArenaStringPtr; // For AllocateAligned.
|
|
|
|
|
friend class internal::LazyField; // For CreateMaybeMessage.
|
|
|
|
|
friend class MessageLite; |
|
|
|
|
template <typename Key, typename T> |
|
|
|
|
friend class Map; |
|
|
|
|
}; |
|
|
|
|