246 inline Arena() : impl_() {}
252 inline Arena(
char* initial_block,
size_t initial_block_size)
253 : impl_(initial_block, initial_block_size) {}
259 options.AllocationPolicy()) {}
267 static const size_t kBlockOverhead =
268 internal::ThreadSafeArena::kBlockHeaderSize +
269 internal::ThreadSafeArena::kSerialArenaSize;
286 template <
typename T,
typename... Args>
287 PROTOBUF_ALWAYS_INLINE
static T* CreateMessage(Arena* arena, Args&&... args) {
289 InternalHelper<T>::is_arena_constructable::value,
290 "CreateMessage can only construct types that are ArenaConstructable");
294 return Arena::CreateMaybeMessage<T>(arena,
static_cast<Args&&
>(args)...);
312 template <
typename T,
typename... Args>
313 PROTOBUF_NDEBUG_INLINE
static T* Create(Arena* arena, Args&&... args) {
314 return CreateInternal<T>(arena, std::is_convertible<T*, MessageLite*>(),
315 static_cast<Args&&
>(args)...);
319 void* AllocateAligned(
size_t size,
size_t align = 8) {
321 return AllocateAlignedNoHook(internal::AlignUpTo8(size));
328 return internal::AlignTo(AllocateAlignedNoHook(size + align - 8), align);
338 template <
typename T>
339 PROTOBUF_NDEBUG_INLINE
static T* CreateArray(Arena* arena,
340 size_t num_elements) {
341 static_assert(std::is_trivial<T>::value,
342 "CreateArray requires a trivially constructible type");
343 static_assert(std::is_trivially_destructible<T>::value,
344 "CreateArray requires a trivially destructible type");
345 GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() /
sizeof(T))
346 <<
"Requested size is too large to fit into size_t.";
348 return static_cast<T*
>(::operator
new[](num_elements *
sizeof(T)));
350 return arena->CreateInternalRawArray<T>(num_elements);
360 uint64_t SpaceAllocated()
const {
return impl_.SpaceAllocated(); }
365 uint64_t SpaceUsed()
const {
return impl_.SpaceUsed(); }
372 uint64_t Reset() {
return impl_.Reset(); }
376 template <
typename T>
377 PROTOBUF_ALWAYS_INLINE
void Own(T*
object) {
378 OwnInternal(
object, std::is_convertible<T*, MessageLite*>());
386 template <
typename T>
387 PROTOBUF_ALWAYS_INLINE
void OwnDestructor(T*
object) {
388 if (
object != NULL) {
389 impl_.AddCleanup(
object, &internal::arena_destruct_object<T>);
397 PROTOBUF_ALWAYS_INLINE
void OwnCustomDestructor(
void*
object,
398 void (*destruct)(
void*)) {
399 impl_.AddCleanup(
object, destruct);
406 template <
typename T>
407 PROTOBUF_ALWAYS_INLINE
static Arena* GetArena(
const T* value) {
408 return GetArenaInternal(value);
411 template <
typename T>
412 class InternalHelper {
415 static Arena* GetOwningArena(
const T* p) {
return p->GetOwningArena(); }
417 static void InternalSwap(T* a, T* b) { a->InternalSwap(b); }
419 static Arena* GetArenaForAllocationInternal(
420 const T* p, std::true_type ) {
421 return p->GetArenaForAllocation();
424 static Arena* GetArenaForAllocationInternal(
425 const T* p, std::false_type ) {
426 return GetArenaForAllocationForNonMessage(
427 p,
typename is_arena_constructable::type());
430 static Arena* GetArenaForAllocationForNonMessage(
431 const T* p, std::true_type ) {
432 return p->GetArena();
435 static Arena* GetArenaForAllocationForNonMessage(
436 const T* p, std::false_type ) {
437 return GetArenaForAllocationForNonMessageNonArenaConstructible(
438 p,
typename has_get_arena::type());
441 static Arena* GetArenaForAllocationForNonMessageNonArenaConstructible(
442 const T* p, std::true_type ) {
443 return p->GetArena();
446 static Arena* GetArenaForAllocationForNonMessageNonArenaConstructible(
447 const T* , std::false_type ) {
451 template <
typename U>
452 static char DestructorSkippable(
const typename U::DestructorSkippable_*);
453 template <
typename U>
454 static double DestructorSkippable(...);
456 typedef std::integral_constant<
457 bool,
sizeof(DestructorSkippable<T>(
static_cast<const T*
>(0))) ==
459 std::is_trivially_destructible<T>::value>
460 is_destructor_skippable;
462 template <
typename U>
463 static char ArenaConstructable(
464 const typename U::InternalArenaConstructable_*);
465 template <
typename U>
466 static double ArenaConstructable(...);
468 typedef std::integral_constant<bool, sizeof(ArenaConstructable<T>(
469 static_cast<const T*
>(0))) ==
471 is_arena_constructable;
473 template <
typename U,
474 typename std::enable_if<
475 std::is_same<Arena*, decltype(std::declval<const U>()
476 .GetArena())>::value,
478 static char HasGetArena(
decltype(&U::GetArena));
479 template <
typename U>
480 static double HasGetArena(...);
482 typedef std::integral_constant<bool, sizeof(HasGetArena<T>(
nullptr)) ==
486 template <
typename... Args>
487 static T* Construct(
void* ptr, Args&&... args) {
488 return new (ptr) T(
static_cast<Args&&
>(args)...);
491 static inline PROTOBUF_ALWAYS_INLINE T* New() {
492 return new T(
nullptr);
495 static Arena* GetArena(
const T* p) {
return p->GetArena(); }
498 friend class TestUtil::ReflectionTester;
503 template <
typename T>
504 static Arena* InternalGetOwningArena(
const T* p) {
505 return InternalHelper<T>::GetOwningArena(p);
510 template <
typename T>
511 static Arena* InternalGetArenaForAllocation(
const T* p) {
512 return InternalHelper<T>::GetArenaForAllocationInternal(
513 p, std::is_convertible<T*, MessageLite*>());
517 static Arena* InternalCreateMessageOwnedArena() {
518 return new Arena(internal::MessageOwned{});
522 bool InternalIsMessageOwnedArena() {
return IsMessageOwned(); }
536 template <
typename T>
537 struct is_arena_constructable : InternalHelper<T>::is_arena_constructable {};
538 template <
typename T>
539 struct is_destructor_skippable : InternalHelper<T>::is_destructor_skippable {
543 internal::ThreadSafeArena impl_;
545 template <
typename T>
546 struct has_get_arena : InternalHelper<T>::has_get_arena {};
549 inline Arena(internal::MessageOwned) : impl_(internal::MessageOwned{}) {}
552 PROTOBUF_ALWAYS_INLINE
bool IsMessageOwned()
const {
553 return impl_.IsMessageOwned();
556 void ReturnArrayMemory(
void* p,
size_t size) {
557 impl_.ReturnArrayMemory(p, size);
560 template <
typename T,
typename... Args>
561 PROTOBUF_NDEBUG_INLINE
static T* CreateMessageInternal(Arena* arena,
564 InternalHelper<T>::is_arena_constructable::value,
565 "CreateMessage can only construct types that are ArenaConstructable");
567 return new T(
nullptr,
static_cast<Args&&
>(args)...);
569 return arena->DoCreateMessage<T>(
static_cast<Args&&
>(args)...);
576 template <
typename T>
577 PROTOBUF_NDEBUG_INLINE
static T* CreateMessageInternal(Arena* arena) {
579 InternalHelper<T>::is_arena_constructable::value,
580 "CreateMessage can only construct types that are ArenaConstructable");
584 return InternalHelper<T>::New();
586 return arena->DoCreateMessage<T>();
592 PROTOBUF_NDEBUG_INLINE
void* AllocateInternal(
size_t size,
size_t align,
593 void (*destructor)(
void*),
594 const std::type_info* type) {
596 if (destructor ==
nullptr) {
597 return AllocateAlignedWithHook(size, align, type);
600 auto res = AllocateAlignedWithCleanup(internal::AlignUpTo8(size), type);
601 res.second->elem = res.first;
602 res.second->cleanup = destructor;
605 auto res = AllocateAlignedWithCleanup(size + align - 8, type);
606 auto ptr = internal::AlignTo(res.first, align);
607 res.second->elem = ptr;
608 res.second->cleanup = destructor;
619 template <
typename Msg,
typename... Args>
620 PROTOBUF_ALWAYS_INLINE
static Msg* DoCreateMaybeMessage(Arena* arena,
623 return CreateMessageInternal<Msg>(arena, std::forward<Args>(args)...);
626 template <
typename T,
typename... Args>
627 PROTOBUF_ALWAYS_INLINE
static T* DoCreateMaybeMessage(Arena* arena,
630 return Create<T>(arena, std::forward<Args>(args)...);
633 template <
typename T,
typename... Args>
634 PROTOBUF_ALWAYS_INLINE
static T* CreateMaybeMessage(Arena* arena,
636 return DoCreateMaybeMessage<T>(arena, is_arena_constructable<T>(),
637 std::forward<Args>(args)...);
642 template <
typename T>
643 PROTOBUF_NDEBUG_INLINE T* CreateInternalRawArray(
size_t num_elements) {
644 GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() /
sizeof(T))
645 <<
"Requested size is too large to fit into size_t.";
648 const size_t n =
sizeof(T) * num_elements;
649 return static_cast<T*
>(
650 AllocateAlignedWithHookForArray(n,
alignof(T),
RTTI_TYPE_ID(T)));
653 template <
typename T,
typename... Args>
654 PROTOBUF_NDEBUG_INLINE T* DoCreateMessage(Args&&... args) {
655 return InternalHelper<T>::Construct(
656 AllocateInternal(
sizeof(T),
alignof(T),
658 InternalHelper<T>::is_destructor_skippable::value,
661 this, std::forward<Args>(args)...);
667 template <
typename T,
typename... Args>
668 static void CreateInArenaStorage(T* ptr, Arena* arena, Args&&... args) {
669 CreateInArenaStorageInternal(ptr, arena,
670 typename is_arena_constructable<T>::type(),
671 std::forward<Args>(args)...);
672 if (arena !=
nullptr) {
673 RegisterDestructorInternal(
675 typename InternalHelper<T>::is_destructor_skippable::type());
679 template <
typename T,
typename... Args>
680 static void CreateInArenaStorageInternal(T* ptr, Arena* arena,
681 std::true_type, Args&&... args) {
682 InternalHelper<T>::Construct(ptr, arena, std::forward<Args>(args)...);
684 template <
typename T,
typename... Args>
685 static void CreateInArenaStorageInternal(T* ptr, Arena* ,
686 std::false_type, Args&&... args) {
687 new (ptr) T(std::forward<Args>(args)...);
690 template <
typename T>
691 static void RegisterDestructorInternal(T* , Arena* ,
693 template <
typename T>
694 static void RegisterDestructorInternal(T* ptr, Arena* arena,
696 arena->OwnDestructor(ptr);
701 template <
typename T,
typename... Args>
702 PROTOBUF_ALWAYS_INLINE
static T* CreateInternal(Arena* arena, std::true_type,
704 if (arena ==
nullptr) {
705 return new T(std::forward<Args>(args)...);
711 new (arena->AllocateInternal(
sizeof(T),
alignof(T), destructor,
713 T(std::forward<Args>(args)...);
717 template <
typename T,
typename... Args>
718 PROTOBUF_ALWAYS_INLINE
static T* CreateInternal(Arena* arena, std::false_type,
720 if (arena ==
nullptr) {
721 return new T(std::forward<Args>(args)...);
726 return new (arena->AllocateInternal(
sizeof(T),
alignof(T), destructor,
728 T(std::forward<Args>(args)...);
737 template <
typename T>
738 PROTOBUF_ALWAYS_INLINE
void OwnInternal(T*
object, std::true_type) {
739 if (
object != NULL) {
740 impl_.AddCleanup(
object, &internal::arena_delete_object<MessageLite>);
743 template <
typename T>
744 PROTOBUF_ALWAYS_INLINE
void OwnInternal(T*
object, std::false_type) {
745 if (
object != NULL) {
746 impl_.AddCleanup(
object, &internal::arena_delete_object<T>);
753 template <
typename T,
typename std::enable_if<
754 is_arena_constructable<T>::value,
int>::type = 0>
755 PROTOBUF_ALWAYS_INLINE
static Arena* GetArenaInternal(
const T* value) {
756 return InternalHelper<T>::GetArena(value);
758 template <
typename T,
759 typename std::enable_if<!is_arena_constructable<T>::value &&
760 has_get_arena<T>::value,
762 PROTOBUF_ALWAYS_INLINE
static Arena* GetArenaInternal(
const T* value) {
763 return value->GetArena();
765 template <
typename T,
766 typename std::enable_if<!is_arena_constructable<T>::value &&
767 !has_get_arena<T>::value,
769 PROTOBUF_ALWAYS_INLINE
static Arena* GetArenaInternal(
const T* value) {
774 template <
typename T>
775 PROTOBUF_ALWAYS_INLINE
static Arena* GetOwningArena(
const T* value) {
776 return GetOwningArenaInternal(
777 value, std::is_convertible<T*, MessageLite*>());
782 template <
typename T>
783 PROTOBUF_ALWAYS_INLINE
static Arena* GetOwningArenaInternal(
784 const T* value, std::true_type) {
785 return InternalHelper<T>::GetOwningArena(value);
787 template <
typename T>
788 PROTOBUF_ALWAYS_INLINE
static Arena* GetOwningArenaInternal(
789 const T* , std::false_type) {
793 void* AllocateAlignedWithHookForArray(
size_t n,
size_t align,
794 const std::type_info* type) {
796 return AllocateAlignedWithHookForArray(internal::AlignUpTo8(n), type);
803 return internal::AlignTo(
804 AllocateAlignedWithHookForArray(n + align - 8, type), align);
808 void* AllocateAlignedWithHook(
size_t n,
size_t align,
809 const std::type_info* type) {
811 return AllocateAlignedWithHook(internal::AlignUpTo8(n), type);
818 return internal::AlignTo(AllocateAlignedWithHook(n + align - 8, type),
823 void* AllocateAlignedNoHook(
size_t n);
824 void* AllocateAlignedWithHook(
size_t n,
const std::type_info* type);
825 void* AllocateAlignedWithHookForArray(
size_t n,
const std::type_info* type);
826 std::pair<void*, internal::SerialArena::CleanupNode*>
827 AllocateAlignedWithCleanup(
size_t n,
const std::type_info* type);
829 template <
typename Type>
831 friend class internal::InternalMetadata;
832 friend class internal::LazyField;
833 friend class internal::EpsCopyInputStream;
835 template <
typename Key,
typename T>
839 friend class internal::RepeatedPtrFieldBase;
840 friend struct internal::ArenaTestPeer;