33 #ifndef GOOGLE_PROTOBUF_ARENA_H__
34 #define GOOGLE_PROTOBUF_ARENA_H__
38 #include <type_traits>
41 #undef max // Visual Studio defines this macro
43 #if defined(_MSC_VER) && !defined(_LIBCPP_STD_VER) && !_HAS_EXCEPTIONS
48 using type_info = ::type_info;
54 #include <type_traits>
55 #include <google/protobuf/arena_impl.h>
56 #include <google/protobuf/port.h>
58 #include <google/protobuf/port_def.inc>
61 #error "You cannot SWIG proto headers"
71 template <
typename Key,
typename T>
74 namespace arena_metrics {
81 class ReflectionTester;
86 struct ArenaStringPtr;
87 class InlinedStringField;
89 class EpsCopyInputStream;
91 template <
typename Type>
92 class GenericTypeHandler;
94 inline PROTOBUF_ALWAYS_INLINE
96 return reinterpret_cast<void*
>(
101 template <
typename T>
103 reinterpret_cast<T*
>(object)->~
T();
106 template <
bool destructor_skippable,
typename T>
108 constexpr
static void (*
destructor)(
void*) = &arena_destruct_object<T>;
111 template <
typename T>
116 template <
typename T>
118 delete reinterpret_cast<T*
>(object);
124 struct ArenaOptions {
149 void* (*block_alloc)(size_t);
193 #define RTTI_TYPE_ID(type) (&typeid(type))
195 #define RTTI_TYPE_ID(type) (NULL)
253 inline Arena(
char* initial_block,
size_t initial_block_size)
254 :
impl_(initial_block, initial_block_size) {}
268 static const size_t kBlockOverhead =
287 template <
typename T,
typename...
Args>
291 "CreateMessage can only construct types that are ArenaConstructable");
295 return Arena::CreateMaybeMessage<T>(
arena,
static_cast<Args&&
>(
args)...);
313 template <
typename T,
typename...
Args>
315 return CreateInternal<T>(
arena, std::is_convertible<T*, MessageLite*>(),
325 template <
typename T>
326 PROTOBUF_NDEBUG_INLINE
static T* CreateArray(
Arena*
arena,
329 "CreateArray requires a trivially constructible type");
331 "CreateArray requires a trivially destructible type");
333 <<
"Requested size is too large to fit into size_t.";
335 return static_cast<T*
>(::operator
new[](
num_elements *
sizeof(
T)));
347 uint64_t SpaceAllocated()
const {
return impl_.SpaceAllocated(); }
363 template <
typename T>
364 PROTOBUF_ALWAYS_INLINE
void Own(
T*
object) {
365 OwnInternal(
object, std::is_convertible<T*, MessageLite*>());
373 template <
typename T>
374 PROTOBUF_ALWAYS_INLINE
void OwnDestructor(
T*
object) {
375 if (
object != NULL) {
376 impl_.AddCleanup(
object, &internal::arena_destruct_object<T>);
384 PROTOBUF_ALWAYS_INLINE
void OwnCustomDestructor(
void*
object,
385 void (*destruct)(
void*)) {
386 impl_.AddCleanup(
object, destruct);
393 template <
typename T>
395 return GetArenaInternal(
value);
398 template <
typename T>
399 class InternalHelper {
402 static Arena* GetOwningArena(
const T* p) {
return p->GetOwningArena(); }
405 static Arena* GetArenaForAllocation(
const T* p) {
406 return GetArenaForAllocationInternal(
407 p, std::is_convertible<T*, MessageLite*>());
411 static Arena* CreateMessageOwnedArena() {
416 static bool IsMessageOwnedArena(
Arena*
arena) {
417 return arena->IsMessageOwned();
421 static Arena* GetArenaForAllocationInternal(
423 return p->GetArenaForAllocation();
426 static Arena* GetArenaForAllocationInternal(
428 return GetArenaForAllocationForNonMessage(
432 static Arena* GetArenaForAllocationForNonMessage(
434 return p->GetArena();
437 static Arena* GetArenaForAllocationForNonMessage(
439 return GetArenaForAllocationForNonMessageNonArenaConstructible(
443 static Arena* GetArenaForAllocationForNonMessageNonArenaConstructible(
445 return p->GetArena();
448 static Arena* GetArenaForAllocationForNonMessageNonArenaConstructible(
453 template <
typename U>
454 static char DestructorSkippable(
const typename U::DestructorSkippable_*);
455 template <
typename U>
456 static double DestructorSkippable(...);
458 typedef std::integral_constant<
459 bool,
sizeof(DestructorSkippable<T>(
static_cast<const T*
>(0))) ==
462 is_destructor_skippable;
464 template <
typename U>
465 static char ArenaConstructable(
466 const typename U::InternalArenaConstructable_*);
467 template <
typename U>
468 static double ArenaConstructable(...);
470 typedef std::integral_constant<bool, sizeof(ArenaConstructable<T>(
471 static_cast<const T*
>(0))) ==
473 is_arena_constructable;
475 template <
typename U,
476 typename std::enable_if<
477 std::is_same<Arena*, decltype(std::declval<const U>()
478 .GetArena())>::
value,
481 template <
typename U>
482 static double HasGetArena(...);
484 typedef std::integral_constant<bool, sizeof(HasGetArena<T>(
nullptr)) ==
488 template <
typename...
Args>
493 static inline PROTOBUF_ALWAYS_INLINE
T*
New() {
494 return new T(
nullptr);
515 template <
typename T>
516 struct is_arena_constructable : InternalHelper<T>::is_arena_constructable {};
517 template <
typename T>
518 struct is_destructor_skippable : InternalHelper<T>::is_destructor_skippable {
524 template <
typename T>
525 struct has_get_arena : InternalHelper<T>::has_get_arena {};
531 PROTOBUF_ALWAYS_INLINE
bool IsMessageOwned()
const {
532 return impl_.IsMessageOwned();
535 template <
typename T,
typename...
Args>
536 PROTOBUF_NDEBUG_INLINE
static T* CreateMessageInternal(
Arena*
arena,
540 "CreateMessage can only construct types that are ArenaConstructable");
542 return new T(
nullptr,
static_cast<Args&&
>(
args)...);
551 template <
typename T>
552 PROTOBUF_NDEBUG_INLINE
static T* CreateMessageInternal(
Arena*
arena) {
555 "CreateMessage can only construct types that are ArenaConstructable");
561 return arena->DoCreateMessage<
T>();
567 PROTOBUF_NDEBUG_INLINE
void* AllocateInternal(
size_t size,
size_t align,
568 void (*destructor)(
void*),
569 const std::type_info*
type) {
571 if (destructor ==
nullptr) {
576 res.second->elem = res.first;
577 res.second->cleanup = destructor;
580 auto res = AllocateAlignedWithCleanup(
size +
align - 8,
type);
582 res.second->elem =
ptr;
583 res.second->cleanup = destructor;
594 template <
typename Msg,
typename...
Args>
595 PROTOBUF_ALWAYS_INLINE
static Msg* DoCreateMaybeMessage(
Arena*
arena,
598 return CreateMessageInternal<Msg>(
arena, std::forward<Args>(
args)...);
601 template <
typename T,
typename...
Args>
602 PROTOBUF_ALWAYS_INLINE
static T* DoCreateMaybeMessage(
Arena*
arena,
605 return Create<T>(
arena, std::forward<Args>(
args)...);
608 template <
typename T,
typename...
Args>
609 PROTOBUF_ALWAYS_INLINE
static T* CreateMaybeMessage(
Arena*
arena,
611 return DoCreateMaybeMessage<T>(
arena, is_arena_constructable<T>(),
612 std::forward<Args>(
args)...);
617 template <
typename T>
618 PROTOBUF_NDEBUG_INLINE
T* CreateInternalRawArray(
size_t num_elements) {
620 <<
"Requested size is too large to fit into size_t.";
624 return static_cast<T*
>(
628 template <
typename T,
typename...
Args>
629 PROTOBUF_NDEBUG_INLINE
T* DoCreateMessage(
Args&&...
args) {
631 AllocateInternal(
sizeof(
T),
alignof(
T),
636 this, std::forward<Args>(
args)...);
642 template <
typename T,
typename...
Args>
644 CreateInArenaStorageInternal(
ptr,
arena,
646 std::forward<Args>(
args)...);
647 if (
arena !=
nullptr) {
648 RegisterDestructorInternal(
654 template <
typename T,
typename...
Args>
659 template <
typename T,
typename...
Args>
660 static void CreateInArenaStorageInternal(
T*
ptr,
Arena* ,
662 new (
ptr)
T(std::forward<Args>(
args)...);
665 template <
typename T>
666 static void RegisterDestructorInternal(
T* ,
Arena* ,
668 template <
typename T>
676 template <
typename T,
typename...
Args>
679 if (
arena ==
nullptr) {
680 return new T(std::forward<Args>(
args)...);
686 new (
arena->AllocateInternal(
sizeof(
T),
alignof(
T), destructor,
688 T(std::forward<Args>(
args)...);
692 template <
typename T,
typename...
Args>
695 if (
arena ==
nullptr) {
696 return new T(std::forward<Args>(
args)...);
701 return new (
arena->AllocateInternal(
sizeof(
T),
alignof(
T), destructor,
703 T(std::forward<Args>(
args)...);
712 template <
typename T>
714 if (
object != NULL) {
715 impl_.AddCleanup(
object, &internal::arena_delete_object<MessageLite>);
718 template <
typename T>
720 if (
object != NULL) {
721 impl_.AddCleanup(
object, &internal::arena_delete_object<T>);
728 template <
typename T,
typename std::enable_if<
730 PROTOBUF_ALWAYS_INLINE
static Arena* GetArenaInternal(
const T*
value) {
733 template <
typename T,
737 PROTOBUF_ALWAYS_INLINE
static Arena* GetArenaInternal(
const T*
value) {
738 return value->GetArena();
740 template <
typename T,
744 PROTOBUF_ALWAYS_INLINE
static Arena* GetArenaInternal(
const T*
value) {
749 template <
typename T>
750 PROTOBUF_ALWAYS_INLINE
static Arena* GetOwningArena(
const T*
value) {
751 return GetOwningArenaInternal(
752 value, std::is_convertible<T*, MessageLite*>());
757 template <
typename T>
758 PROTOBUF_ALWAYS_INLINE
static Arena* GetOwningArenaInternal(
760 return InternalHelper<T>::GetOwningArena(
value);
762 template <
typename T>
763 PROTOBUF_ALWAYS_INLINE
static Arena* GetOwningArenaInternal(
769 void* AllocateAligned(
size_t n,
size_t align = 8) {
782 void* AllocateAlignedWithHook(
size_t n,
size_t align,
783 const std::type_info*
type) {
797 void* AllocateAlignedNoHook(
size_t n);
798 void* AllocateAlignedWithHook(
size_t n,
const std::type_info*
type);
799 std::pair<void*, internal::SerialArena::CleanupNode*>
800 AllocateAlignedWithCleanup(
size_t n,
const std::type_info*
type);
802 template <
typename Type>
806 friend class internal::LazyField;
809 template <
typename Key,
typename T>
819 #include <google/protobuf/port_undef.inc>
821 #endif // GOOGLE_PROTOBUF_ARENA_H__