33 #ifndef GOOGLE_PROTOBUF_ARENA_IMPL_H__
34 #define GOOGLE_PROTOBUF_ARENA_IMPL_H__
40 #include <google/protobuf/stubs/common.h>
41 #include <google/protobuf/stubs/logging.h>
43 #ifdef ADDRESS_SANITIZER
44 #include <sanitizer/asan_interface.h>
45 #endif // ADDRESS_SANITIZER
47 #include <google/protobuf/port_def.inc>
56 return (n + 7) &
static_cast<size_t>(-8);
69 virtual void OnDestroy(
uint64_t space_allocated) = 0;
73 virtual void OnReset(
uint64_t space_allocated) = 0;
81 virtual void OnAlloc(
const std::type_info* allocated_type,
100 void* (*block_alloc)(size_t) =
nullptr;
138 return static_cast<bool>(get_mask<kUserOwnedInitialBlock>());
141 set_mask<kUserOwnedInitialBlock>(
v);
145 return static_cast<bool>(get_mask<kRecordAllocs>());
165 template <u
intptr_t kMask>
169 template <u
intptr_t kMask>
207 return space_allocated_.load(std::memory_order_relaxed);
211 bool HasSpace(
size_t n) {
return n <= static_cast<size_t>(limit_ -
ptr_); }
216 if (PROTOBUF_PREDICT_FALSE(!HasSpace(
n))) {
217 return AllocateAlignedFallback(
n, policy);
219 return AllocateFromExisting(
n);
226 #ifdef ADDRESS_SANITIZER
227 ASAN_UNPOISON_MEMORY_REGION(
ret,
n);
228 #endif // ADDRESS_SANITIZER
237 if (PROTOBUF_PREDICT_FALSE(!HasSpace(
n)))
return false;
238 *
out = AllocateFromExisting(
n);
245 if (PROTOBUF_PREDICT_FALSE(!HasSpace(
n + kCleanupSize))) {
246 return AllocateAlignedWithCleanupFallback(
n, policy);
248 return AllocateFromExistingWithCleanupFallback(
n);
256 limit_ -= kCleanupSize;
257 #ifdef ADDRESS_SANITIZER
258 ASAN_UNPOISON_MEMORY_REGION(
ret,
n);
259 ASAN_UNPOISON_MEMORY_REGION(limit_, kCleanupSize);
260 #endif // ADDRESS_SANITIZER
267 auto res = AllocateAlignedWithCleanup(0, policy);
268 res.second->elem =
elem;
272 void*
owner()
const {
return owner_; }
278 friend class ArenaBenchmark;
284 template <
typename Deallocator>
294 return reinterpret_cast<char*
>(
this) +
n;
306 size_t space_used_ = 0;
318 std::pair<void*, CleanupNode*> AllocateAlignedWithCleanupFallback(
357 InitializeWithPolicy(
mem,
size, policy);
373 if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
374 GetSerialArenaFast(&
arena))) {
375 return arena->AllocateAligned(
n, AllocPolicy());
377 return AllocateAlignedFallback(
n,
type);
388 if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
389 GetSerialArenaFromThreadCache(&
a))) {
390 return a->MaybeAllocateAligned(
n,
out);
395 std::pair<void*, SerialArena::CleanupNode*> AllocateAlignedWithCleanup(
396 size_t n,
const std::type_info*
type);
399 void AddCleanup(
void*
elem,
void (*
cleanup)(
void*));
403 return tag_and_id_ & kMessageOwnedArena;
419 void InitializeFrom(
void*
mem,
size_t size);
421 void* AllocateAlignedFallback(
size_t n,
const std::type_info*
type);
422 std::pair<void*, SerialArena::CleanupNode*>
423 AllocateAlignedWithCleanupFallback(
size_t n,
const std::type_info*
type);
426 void SetInitialBlock(
void*
mem,
size_t size);
432 return tag_and_id_ & ~kMessageOwnedArena;
436 thread_cache().last_serial_arena = serial;
437 thread_cache().last_lifecycle_id_seen = tag_and_id_;
442 hint_.store(serial, std::memory_order_release);
446 if (GetSerialArenaFromThreadCache(
arena))
return true;
451 SerialArena* serial = hint_.load(std::memory_order_acquire);
452 if (PROTOBUF_PREDICT_TRUE(serial != NULL && serial->
owner() == tc)) {
473 template <
typename Functor>
479 for (; serial; serial = serial->
next())
fn(serial);
488 #pragma warning(disable : 4324)
491 #if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
496 : next_lifecycle_id(0),
497 last_lifecycle_id_seen(-1),
498 last_serial_arena(NULL) {}
505 static constexpr
size_t kPerThreadIds = 256;
519 #pragma warning(disable : 4324)
522 std::atomic<LifecycleIdAtomic>
id;
525 #if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
529 #elif defined(PROTOBUF_USE_DLLS)
548 static constexpr
size_t kSerialArenaSize =
549 (
sizeof(
SerialArena) + 7) &
static_cast<size_t>(-8);
550 static_assert(kBlockHeaderSize % 8 == 0,
551 "kBlockHeaderSize must be a multiple of 8.");
552 static_assert(kSerialArenaSize % 8 == 0,
553 "kSerialArenaSize must be a multiple of 8.");
560 #include <google/protobuf/port_undef.inc>
562 #endif // GOOGLE_PROTOBUF_ARENA_IMPL_H__