arena.h
Go to the documentation of this file.
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // This file defines an Arena allocator for better allocation performance.
32 
33 #ifndef GOOGLE_PROTOBUF_ARENA_H__
34 #define GOOGLE_PROTOBUF_ARENA_H__
35 
36 #include <limits>
37 #include <type_traits>
38 #include <utility>
39 #ifdef max
40 #undef max // Visual Studio defines this macro
41 #endif
42 #if defined(_MSC_VER) && !defined(_LIBCPP_STD_VER) && !_HAS_EXCEPTIONS
43 // Work around bugs in MSVC <typeinfo> header when _HAS_EXCEPTIONS=0.
44 #include <exception>
45 #include <typeinfo>
46 namespace std {
47 using type_info = ::type_info;
48 }
49 #else
50 #include <typeinfo>
51 #endif
52 
54 #include <google/protobuf/port.h>
55 #include <type_traits>
56 
57 #include <google/protobuf/port_def.inc>
58 
59 #ifdef SWIG
60 #error "You cannot SWIG proto headers"
61 #endif
62 
63 namespace google {
64 namespace protobuf {
65 
66 struct ArenaOptions; // defined below
67 
68 } // namespace protobuf
69 } // namespace google
70 
71 
72 namespace google {
73 namespace protobuf {
74 
75 class Arena; // defined below
76 class Message; // defined in message.h
77 class MessageLite;
78 
79 namespace arena_metrics {
80 
82 
83 } // namespace arena_metrics
84 
85 namespace internal {
86 
87 struct ArenaStringPtr; // defined in arenastring.h
88 class LazyField; // defined in lazy_field.h
89 
90 template <typename Type>
91 class GenericTypeHandler; // defined in repeated_field.h
92 
93 // Templated cleanup methods.
94 template <typename T>
95 void arena_destruct_object(void* object) {
96  reinterpret_cast<T*>(object)->~T();
97 }
98 template <typename T>
99 void arena_delete_object(void* object) {
100  delete reinterpret_cast<T*>(object);
101 }
102 inline void arena_free(void* object, size_t size) {
103 #if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation)
104  ::operator delete(object, size);
105 #else
106  (void)size;
107  ::operator delete(object);
108 #endif
109 }
110 
111 } // namespace internal
112 
113 // ArenaOptions provides optional additional parameters to arena construction
114 // that control its block-allocation behavior.
115 struct ArenaOptions {
116  // This defines the size of the first block requested from the system malloc.
117  // Subsequent block sizes will increase in a geometric series up to a maximum.
119 
120  // This defines the maximum block size requested from system malloc (unless an
121  // individual arena allocation request occurs with a size larger than this
122  // maximum). Requested block sizes increase up to this value, then remain
123  // here.
125 
126  // An initial block of memory for the arena to use, or NULL for none. If
127  // provided, the block must live at least as long as the arena itself. The
128  // creator of the Arena retains ownership of the block after the Arena is
129  // destroyed.
131 
132  // The size of the initial block, if provided.
134 
135  // A function pointer to an alloc method that returns memory blocks of size
136  // requested. By default, it contains a ptr to the malloc function.
137  //
138  // NOTE: block_alloc and dealloc functions are expected to behave like
139  // malloc and free, including Asan poisoning.
140  void* (*block_alloc)(size_t);
141  // A function pointer to a dealloc method that takes ownership of the blocks
142  // from the arena. By default, it contains a ptr to a wrapper function that
143  // calls free.
144  void (*block_dealloc)(void*, size_t);
145 
151  block_alloc(&::operator new),
157 
158  private:
159  // Hooks for adding external functionality such as user-specific metrics
160  // collection, specific debugging abilities, etc.
161  // Init hook (if set) will always be called at Arena init time. Init hook may
162  // return a pointer to a cookie to be stored in the arena. Reset and
163  // destruction hooks will then be called with the same cookie pointer. This
164  // allows us to save an external object per arena instance and use it on the
165  // other hooks (Note: If init hook returns NULL, the other hooks will NOT be
166  // called on this arena instance).
167  // on_arena_reset and on_arena_destruction also receive the space used in the
168  // arena just before the reset.
169  void* (*on_arena_init)(Arena* arena);
170  void (*on_arena_reset)(Arena* arena, void* cookie, uint64 space_used);
171  void (*on_arena_destruction)(Arena* arena, void* cookie, uint64 space_used);
172 
173  // type_info is promised to be static - its lifetime extends to
174  // match program's lifetime (It is given by typeid operator).
175  // Note: typeid(void) will be passed as allocated_type every time we
176  // intentionally want to avoid monitoring an allocation. (i.e. internal
177  // allocations for managing the arena)
178  void (*on_arena_allocation)(const std::type_info* allocated_type,
179  uint64 alloc_size, void* cookie);
180 
181  // Constants define default starting block size and max block size for
182  // arena allocator behavior -- see descriptions above.
183  static const size_t kDefaultStartBlockSize = 256;
184  static const size_t kDefaultMaxBlockSize = 8192;
185 
187  friend class Arena;
189 };
190 
191 // Support for non-RTTI environments. (The metrics hooks API uses type
192 // information.)
193 #if PROTOBUF_RTTI
194 #define RTTI_TYPE_ID(type) (&typeid(type))
195 #else
196 #define RTTI_TYPE_ID(type) (NULL)
197 #endif
198 
199 // Arena allocator. Arena allocation replaces ordinary (heap-based) allocation
200 // with new/delete, and improves performance by aggregating allocations into
201 // larger blocks and freeing allocations all at once. Protocol messages are
202 // allocated on an arena by using Arena::CreateMessage<T>(Arena*), below, and
203 // are automatically freed when the arena is destroyed.
204 //
205 // This is a thread-safe implementation: multiple threads may allocate from the
206 // arena concurrently. Destruction is not thread-safe and the destructing
207 // thread must synchronize with users of the arena first.
208 //
209 // An arena provides two allocation interfaces: CreateMessage<T>, which works
210 // for arena-enabled proto2 message types as well as other types that satisfy
211 // the appropriate protocol (described below), and Create<T>, which works for
212 // any arbitrary type T. CreateMessage<T> is better when the type T supports it,
213 // because this interface (i) passes the arena pointer to the created object so
214 // that its sub-objects and internal allocations can use the arena too, and (ii)
215 // elides the object's destructor call when possible. Create<T> does not place
216 // any special requirements on the type T, and will invoke the object's
217 // destructor when the arena is destroyed.
218 //
219 // The arena message allocation protocol, required by CreateMessage<T>, is as
220 // follows:
221 //
222 // - The type T must have (at least) two constructors: a constructor with no
223 // arguments, called when a T is allocated on the heap; and a constructor with
224 // a Arena* argument, called when a T is allocated on an arena. If the
225 // second constructor is called with a NULL arena pointer, it must be
226 // equivalent to invoking the first (no-argument) constructor.
227 //
228 // - The type T must have a particular type trait: a nested type
229 // |InternalArenaConstructable_|. This is usually a typedef to |void|. If no
230 // such type trait exists, then the instantiation CreateMessage<T> will fail
231 // to compile.
232 //
233 // - The type T *may* have the type trait |DestructorSkippable_|. If this type
234 // trait is present in the type, then its destructor will not be called if and
235 // only if it was passed a non-NULL arena pointer. If this type trait is not
236 // present on the type, then its destructor is always called when the
237 // containing arena is destroyed.
238 //
239 // - One- and two-user-argument forms of CreateMessage<T>() also exist that
240 // forward these constructor arguments to T's constructor: for example,
241 // CreateMessage<T>(Arena*, arg1, arg2) forwards to a constructor T(Arena*,
242 // arg1, arg2).
243 //
244 // This protocol is implemented by all arena-enabled proto2 message classes as
245 // well as protobuf container types like RepeatedPtrField and Map. The protocol
246 // is internal to protobuf and is not guaranteed to be stable. Non-proto types
247 // should not rely on this protocol.
248 class PROTOBUF_EXPORT alignas(8) Arena final {
249  public:
250  // Arena constructor taking custom options. See ArenaOptions below for
251  // descriptions of the options available.
252  explicit Arena(const ArenaOptions& options) : impl_(options) {
253  Init(options);
254  }
255 
256  // Block overhead. Use this as a guide for how much to over-allocate the
257  // initial block if you want an allocation of size N to fit inside it.
258  //
259  // WARNING: if you allocate multiple objects, it is difficult to guarantee
260  // that a series of allocations will fit in the initial block, especially if
261  // Arena changes its alignment guarantees in the future!
262  static const size_t kBlockOverhead = internal::ArenaImpl::kBlockHeaderSize +
264 
265  // Default constructor with sensible default options, tuned for average
266  // use-cases.
267  Arena() : impl_(ArenaOptions()) { Init(ArenaOptions()); }
268 
269  ~Arena() {
270  if (hooks_cookie_) {
271  CallDestructorHooks();
272  }
273  }
274 
275  void Init(const ArenaOptions& options) {
276  on_arena_allocation_ = options.on_arena_allocation;
277  on_arena_reset_ = options.on_arena_reset;
278  on_arena_destruction_ = options.on_arena_destruction;
279  // Call the initialization hook
280  if (options.on_arena_init != NULL) {
281  hooks_cookie_ = options.on_arena_init(this);
282  } else {
283  hooks_cookie_ = NULL;
284  }
285  }
286 
287  // API to create proto2 message objects on the arena. If the arena passed in
288  // is NULL, then a heap allocated object is returned. Type T must be a message
289  // defined in a .proto file with cc_enable_arenas set to true, otherwise a
290  // compilation error will occur.
291  //
292  // RepeatedField and RepeatedPtrField may also be instantiated directly on an
293  // arena with this method.
294  //
295  // This function also accepts any type T that satisfies the arena message
296  // allocation protocol, documented above.
297  template <typename T, typename... Args>
298  PROTOBUF_ALWAYS_INLINE static T* CreateMessage(Arena* arena, Args&&... args) {
299  static_assert(
301  "CreateMessage can only construct types that are ArenaConstructable");
302  // We must delegate to CreateMaybeMessage() and NOT CreateMessageInternal()
303  // because protobuf generated classes specialize CreateMaybeMessage() and we
304  // need to use that specialization for code size reasons.
305  return Arena::CreateMaybeMessage<T>(arena, std::forward<Args>(args)...);
306  }
307 
308  // API to create any objects on the arena. Note that only the object will
309  // be created on the arena; the underlying ptrs (in case of a proto2 message)
310  // will be still heap allocated. Proto messages should usually be allocated
311  // with CreateMessage<T>() instead.
312  //
313  // Note that even if T satisfies the arena message construction protocol
314  // (InternalArenaConstructable_ trait and optional DestructorSkippable_
315  // trait), as described above, this function does not follow the protocol;
316  // instead, it treats T as a black-box type, just as if it did not have these
317  // traits. Specifically, T's constructor arguments will always be only those
318  // passed to Create<T>() -- no additional arena pointer is implicitly added.
319  // Furthermore, the destructor will always be called at arena destruction time
320  // (unless the destructor is trivial). Hence, from T's point of view, it is as
321  // if the object were allocated on the heap (except that the underlying memory
322  // is obtained from the arena).
323  template <typename T, typename... Args>
324  PROTOBUF_ALWAYS_INLINE static T* Create(Arena* arena, Args&&... args) {
325  return CreateNoMessage<T>(arena, is_arena_constructable<T>(),
326  std::forward<Args>(args)...);
327  }
328 
329  // Create an array of object type T on the arena *without* invoking the
330  // constructor of T. If `arena` is null, then the return value should be freed
331  // with `delete[] x;` (or `::operator delete[](x);`).
332  // To ensure safe uses, this function checks at compile time
333  // (when compiled as C++11) that T is trivially default-constructible and
334  // trivially destructible.
335  template <typename T>
336  PROTOBUF_ALWAYS_INLINE static T* CreateArray(Arena* arena,
337  size_t num_elements) {
338  static_assert(std::is_pod<T>::value,
339  "CreateArray requires a trivially constructible type");
341  "CreateArray requires a trivially destructible type");
342  GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
343  << "Requested size is too large to fit into size_t.";
344  if (arena == NULL) {
345  return static_cast<T*>(::operator new[](num_elements * sizeof(T)));
346  } else {
347  return arena->CreateInternalRawArray<T>(num_elements);
348  }
349  }
350 
351  // Returns the total space allocated by the arena, which is the sum of the
352  // sizes of the underlying blocks. This method is relatively fast; a counter
353  // is kept as blocks are allocated.
354  uint64 SpaceAllocated() const { return impl_.SpaceAllocated(); }
355  // Returns the total space used by the arena. Similar to SpaceAllocated but
356  // does not include free space and block overhead. The total space returned
357  // may not include space used by other threads executing concurrently with
358  // the call to this method.
359  uint64 SpaceUsed() const { return impl_.SpaceUsed(); }
360  // DEPRECATED. Please use SpaceAllocated() and SpaceUsed().
361  //
362  // Combines SpaceAllocated and SpaceUsed. Returns a pair of
363  // <space_allocated, space_used>.
364  PROTOBUF_DEPRECATED_MSG("Please use SpaceAllocated() and SpaceUsed()")
365  std::pair<uint64, uint64> SpaceAllocatedAndUsed() const {
366  return std::make_pair(SpaceAllocated(), SpaceUsed());
367  }
368 
369  // Frees all storage allocated by this arena after calling destructors
370  // registered with OwnDestructor() and freeing objects registered with Own().
371  // Any objects allocated on this arena are unusable after this call. It also
372  // returns the total space used by the arena which is the sums of the sizes
373  // of the allocated blocks. This method is not thread-safe.
374  PROTOBUF_NOINLINE uint64 Reset() {
375  // Call the reset hook
376  if (on_arena_reset_ != NULL) {
377  on_arena_reset_(this, hooks_cookie_, impl_.SpaceAllocated());
378  }
379  return impl_.Reset();
380  }
381 
382  // Adds |object| to a list of heap-allocated objects to be freed with |delete|
383  // when the arena is destroyed or reset.
384  template <typename T>
385  PROTOBUF_NOINLINE void Own(T* object) {
386  OwnInternal(object, std::is_convertible<T*, Message*>());
387  }
388 
389  // Adds |object| to a list of objects whose destructors will be manually
390  // called when the arena is destroyed or reset. This differs from Own() in
391  // that it does not free the underlying memory with |delete|; hence, it is
392  // normally only used for objects that are placement-newed into
393  // arena-allocated memory.
394  template <typename T>
395  PROTOBUF_NOINLINE void OwnDestructor(T* object) {
396  if (object != NULL) {
397  impl_.AddCleanup(object, &internal::arena_destruct_object<T>);
398  }
399  }
400 
401  // Adds a custom member function on an object to the list of destructors that
402  // will be manually called when the arena is destroyed or reset. This differs
403  // from OwnDestructor() in that any member function may be specified, not only
404  // the class destructor.
405  PROTOBUF_NOINLINE void OwnCustomDestructor(void* object,
406  void (*destruct)(void*)) {
407  impl_.AddCleanup(object, destruct);
408  }
409 
410  // Retrieves the arena associated with |value| if |value| is an arena-capable
411  // message, or NULL otherwise. If possible, the call resolves at compile time.
412  // Note that we can often devirtualize calls to `value->GetArena()` so usually
413  // calling this method is unnecessary.
414  template <typename T>
415  PROTOBUF_ALWAYS_INLINE static Arena* GetArena(const T* value) {
416  return GetArenaInternal(value);
417  }
418 
419  template <typename T>
420  class InternalHelper {
421  template <typename U>
422  static char DestructorSkippable(const typename U::DestructorSkippable_*);
423  template <typename U>
424  static double DestructorSkippable(...);
425 
426  typedef std::integral_constant<
427  bool, sizeof(DestructorSkippable<T>(static_cast<const T*>(0))) ==
428  sizeof(char) ||
430  is_destructor_skippable;
431 
432  template <typename U>
433  static char ArenaConstructable(
434  const typename U::InternalArenaConstructable_*);
435  template <typename U>
436  static double ArenaConstructable(...);
437 
438  typedef std::integral_constant<bool, sizeof(ArenaConstructable<T>(
439  static_cast<const T*>(0))) ==
440  sizeof(char)>
441  is_arena_constructable;
442 
443  template <typename U,
444  typename std::enable_if<
445  std::is_same<Arena*, decltype(std::declval<const U>()
446  .GetArena())>::value,
447  int>::type = 0>
448  static char HasGetArena(decltype(&U::GetArena));
449  template <typename U>
450  static double HasGetArena(...);
451 
452  typedef std::integral_constant<bool, sizeof(HasGetArena<T>(nullptr)) ==
453  sizeof(char)>
454  has_get_arena;
455 
456  template <typename... Args>
457  static T* Construct(void* ptr, Args&&... args) {
458  return new (ptr) T(std::forward<Args>(args)...);
459  }
460 
461  static Arena* GetArena(const T* p) { return p->GetArenaNoVirtual(); }
462 
463  friend class Arena;
464  };
465 
466  // Helper typetraits that indicates support for arenas in a type T at compile
467  // time. This is public only to allow construction of higher-level templated
468  // utilities.
469  //
470  // is_arena_constructable<T>::value is true if the message type T has arena
471  // support enabled, and false otherwise.
472  //
473  // is_destructor_skippable<T>::value is true if the message type T has told
474  // the arena that it is safe to skip the destructor, and false otherwise.
475  //
476  // This is inside Arena because only Arena has the friend relationships
477  // necessary to see the underlying generated code traits.
478  template <typename T>
479  struct is_arena_constructable : InternalHelper<T>::is_arena_constructable {};
480  template <typename T>
481  struct is_destructor_skippable : InternalHelper<T>::is_destructor_skippable {
482  };
483 
484  private:
485  template <typename T>
486  struct has_get_arena : InternalHelper<T>::has_get_arena {};
487 
488  template <typename T, typename... Args>
489  PROTOBUF_ALWAYS_INLINE static T* CreateMessageInternal(Arena* arena,
490  Args&&... args) {
491  static_assert(
493  "CreateMessage can only construct types that are ArenaConstructable");
494  if (arena == NULL) {
495  return new T(nullptr, std::forward<Args>(args)...);
496  } else {
497  return arena->DoCreateMessage<T>(std::forward<Args>(args)...);
498  }
499  }
500 
501  // This specialization for no arguments is necessary, because its behavior is
502  // slightly different. When the arena pointer is nullptr, it calls T()
503  // instead of T(nullptr).
504  template <typename T>
505  PROTOBUF_ALWAYS_INLINE static T* CreateMessageInternal(Arena* arena) {
506  static_assert(
508  "CreateMessage can only construct types that are ArenaConstructable");
509  if (arena == NULL) {
510  return new T();
511  } else {
512  return arena->DoCreateMessage<T>();
513  }
514  }
515 
516  template <typename T, typename... Args>
517  PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena,
518  Args&&... args) {
519  if (arena == NULL) {
520  return new T(std::forward<Args>(args)...);
521  } else {
522  return arena->DoCreate<T>(std::is_trivially_destructible<T>::value,
523  std::forward<Args>(args)...);
524  }
525  }
526 
527  void CallDestructorHooks();
528  void OnArenaAllocation(const std::type_info* allocated_type, size_t n) const;
529  inline void AllocHook(const std::type_info* allocated_type, size_t n) const {
530  if (PROTOBUF_PREDICT_FALSE(hooks_cookie_ != NULL)) {
531  OnArenaAllocation(allocated_type, n);
532  }
533  }
534 
535  // Allocate and also optionally call on_arena_allocation callback with the
536  // allocated type info when the hooks are in place in ArenaOptions and
537  // the cookie is not null.
538  template <typename T>
539  PROTOBUF_ALWAYS_INLINE void* AllocateInternal(bool skip_explicit_ownership) {
540  const size_t n = internal::AlignUpTo8(sizeof(T));
541  AllocHook(RTTI_TYPE_ID(T), n);
542  // Monitor allocation if needed.
543  if (skip_explicit_ownership) {
544  return impl_.AllocateAligned(n);
545  } else {
546  return impl_.AllocateAlignedAndAddCleanup(
547  n, &internal::arena_destruct_object<T>);
548  }
549  }
550 
551  // CreateMessage<T> requires that T supports arenas, but this private method
552  // works whether or not T supports arenas. These are not exposed to user code
553  // as it can cause confusing API usages, and end up having double free in
554  // user code. These are used only internally from LazyField and Repeated
555  // fields, since they are designed to work in all mode combinations.
556  template <typename Msg, typename... Args>
557  PROTOBUF_ALWAYS_INLINE static Msg* DoCreateMaybeMessage(Arena* arena,
559  Args&&... args) {
560  return CreateMessageInternal<Msg>(arena, std::forward<Args>(args)...);
561  }
562 
563  template <typename T, typename... Args>
564  PROTOBUF_ALWAYS_INLINE static T* DoCreateMaybeMessage(Arena* arena,
566  Args&&... args) {
567  return CreateInternal<T>(arena, std::forward<Args>(args)...);
568  }
569 
570  template <typename T, typename... Args>
571  PROTOBUF_ALWAYS_INLINE static T* CreateMaybeMessage(Arena* arena,
572  Args&&... args) {
573  return DoCreateMaybeMessage<T>(arena, is_arena_constructable<T>(),
574  std::forward<Args>(args)...);
575  }
576 
577  template <typename T, typename... Args>
578  PROTOBUF_ALWAYS_INLINE static T* CreateNoMessage(Arena* arena, std::true_type,
579  Args&&... args) {
580  // User is constructing with Create() despite the fact that T supports arena
581  // construction. In this case we have to delegate to CreateInternal(), and
582  // we can't use any CreateMaybeMessage() specialization that may be defined.
583  return CreateInternal<T>(arena, std::forward<Args>(args)...);
584  }
585 
586  template <typename T, typename... Args>
587  PROTOBUF_ALWAYS_INLINE static T* CreateNoMessage(Arena* arena,
589  Args&&... args) {
590  // User is constructing with Create() and the type does not support arena
591  // construction. In this case we can delegate to CreateMaybeMessage() and
592  // use any specialization that may be available for that.
593  return CreateMaybeMessage<T>(arena, std::forward<Args>(args)...);
594  }
595 
596  // Just allocate the required size for the given type assuming the
597  // type has a trivial constructor.
598  template <typename T>
599  PROTOBUF_ALWAYS_INLINE T* CreateInternalRawArray(size_t num_elements) {
600  GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
601  << "Requested size is too large to fit into size_t.";
602  const size_t n = internal::AlignUpTo8(sizeof(T) * num_elements);
603  // Monitor allocation if needed.
604  AllocHook(RTTI_TYPE_ID(T), n);
605  return static_cast<T*>(impl_.AllocateAligned(n));
606  }
607 
608  template <typename T, typename... Args>
609  PROTOBUF_ALWAYS_INLINE T* DoCreate(bool skip_explicit_ownership,
610  Args&&... args) {
611  return new (AllocateInternal<T>(skip_explicit_ownership))
612  T(std::forward<Args>(args)...);
613  }
614  template <typename T, typename... Args>
615  PROTOBUF_ALWAYS_INLINE T* DoCreateMessage(Args&&... args) {
616  return InternalHelper<T>::Construct(
618  this, std::forward<Args>(args)...);
619  }
620 
621  // CreateInArenaStorage is used to implement map field. Without it,
622  // Map need to call generated message's protected arena constructor,
623  // which needs to declare Map as friend of generated message.
624  template <typename T>
625  static void CreateInArenaStorage(T* ptr, Arena* arena) {
626  CreateInArenaStorageInternal(ptr, arena,
628  RegisterDestructorInternal(
629  ptr, arena,
631  }
632 
633  template <typename T>
634  static void CreateInArenaStorageInternal(T* ptr, Arena* arena,
635  std::true_type) {
636  InternalHelper<T>::Construct(ptr, arena);
637  }
638  template <typename T>
639  static void CreateInArenaStorageInternal(T* ptr, Arena* /* arena */,
640  std::false_type) {
641  new (ptr) T();
642  }
643 
644  template <typename T>
645  static void RegisterDestructorInternal(T* /* ptr */, Arena* /* arena */,
646  std::true_type) {}
647  template <typename T>
648  static void RegisterDestructorInternal(T* ptr, Arena* arena,
649  std::false_type) {
650  arena->OwnDestructor(ptr);
651  }
652 
653  // These implement Own(), which registers an object for deletion (destructor
654  // call and operator delete()). The second parameter has type 'true_type' if T
655  // is a subtype of Message and 'false_type' otherwise. Collapsing
656  // all template instantiations to one for generic Message reduces code size,
657  // using the virtual destructor instead.
658  template <typename T>
659  PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::true_type) {
660  if (object != NULL) {
661  impl_.AddCleanup(object, &internal::arena_delete_object<Message>);
662  }
663  }
664  template <typename T>
665  PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::false_type) {
666  if (object != NULL) {
667  impl_.AddCleanup(object, &internal::arena_delete_object<T>);
668  }
669  }
670 
671  // Implementation for GetArena(). Only message objects with
672  // InternalArenaConstructable_ tags can be associated with an arena, and such
673  // objects must implement a GetArenaNoVirtual() method.
674  template <typename T, typename std::enable_if<
676  PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
678  }
679  template <typename T,
682  int>::type = 0>
683  PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
684  return value->GetArena();
685  }
686  template <typename T,
689  int>::type = 0>
690  PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
691  return nullptr;
692  }
693 
694  // For friends of arena.
695  void* AllocateAligned(size_t n) {
696  AllocHook(NULL, n);
697  return impl_.AllocateAligned(internal::AlignUpTo8(n));
698  }
699 
700  internal::ArenaImpl impl_;
701 
702  void (*on_arena_allocation_)(const std::type_info* allocated_type,
703  uint64 alloc_size, void* cookie);
704  void (*on_arena_reset_)(Arena* arena, void* cookie, uint64 space_used);
705  void (*on_arena_destruction_)(Arena* arena, void* cookie, uint64 space_used);
706 
707  // The arena may save a cookie it receives from the external on_init hook
708  // and then use it when calling the on_reset and on_destruction hooks.
709  void* hooks_cookie_;
710 
711  template <typename Type>
712  friend class internal::GenericTypeHandler;
713  friend struct internal::ArenaStringPtr; // For AllocateAligned.
714  friend class internal::LazyField; // For CreateMaybeMessage.
715  friend class MessageLite;
716  template <typename Key, typename T>
717  friend class Map;
718 };
719 
720 // Defined above for supporting environments without RTTI.
721 #undef RTTI_TYPE_ID
722 
723 } // namespace protobuf
724 } // namespace google
725 
726 #include <google/protobuf/port_undef.inc>
727 
728 #endif // GOOGLE_PROTOBUF_ARENA_H__
google::protobuf::ArenaOptions::ArenaOptions
ArenaOptions()
Definition: arena.h:146
google::protobuf.internal::GetArena
Arena * GetArena(MessageLite *msg, int64 arena_offset)
Definition: generated_message_table_driven_lite.h:86
NULL
NULL
Definition: test_security_zap.cpp:405
options
Message * options
Definition: src/google/protobuf/descriptor.cc:3119
google::protobuf.internal::AlignUpTo8
size_t AlignUpTo8(size_t n)
Definition: arena_impl.h:53
google::protobuf::python::cmessage::Init
static int Init(CMessage *self, PyObject *args, PyObject *kwargs)
Definition: python/google/protobuf/pyext/message.cc:1286
google::protobuf::ArenaOptions::block_alloc
void *(* block_alloc)(size_t)
Definition: arena.h:140
google::protobuf::MessageLite
Definition: message_lite.h:183
google::protobuf::ArenaOptions::on_arena_allocation
void(* on_arena_allocation)(const std::type_info *allocated_type, uint64 alloc_size, void *cookie)
Definition: arena.h:178
port.h
T
#define T(upbtypeconst, upbtype, ctype, default_value)
google::protobuf::ArenaOptions::on_arena_destruction
void(* on_arena_destruction)(Arena *arena, void *cookie, uint64 space_used)
Definition: arena.h:171
google::protobuf::ArenaOptions::start_block_size
size_t start_block_size
Definition: arena.h:118
RTTI_TYPE_ID
#define RTTI_TYPE_ID(type)
Definition: arena.h:196
mox.Reset
def Reset(*args)
Definition: mox.py:257
google::protobuf::ArenaOptions::initial_block
char * initial_block
Definition: arena.h:130
google::protobuf::ArenaOptionsTestFriend
Definition: arena_unittest.cc:1424
google::protobuf.internal::false_type
integral_constant< bool, false > false_type
Definition: template_util.h:90
p
const char * p
Definition: gmock-matchers_test.cc:3863
google::protobuf.internal::ArenaImpl::kSerialArenaSize
static const size_t kSerialArenaSize
Definition: arena_impl.h:312
google::protobuf::uint64
uint64_t uint64
Definition: protobuf/src/google/protobuf/stubs/port.h:156
size
#define size
Definition: glcorearb.h:2944
google::protobuf.internal::true_type
integral_constant< bool, true > true_type
Definition: template_util.h:89
GOOGLE_CHECK_LE
#define GOOGLE_CHECK_LE(A, B)
Definition: logging.h:159
void
typedef void(APIENTRY *GLDEBUGPROCARB)(GLenum source
n
GLdouble n
Definition: glcorearb.h:4153
type
GLenum type
Definition: glcorearb.h:2695
google::protobuf::ArenaOptions
Definition: arena.h:115
google::protobuf.internal::ArenaImpl
Definition: arena_impl.h:66
google::protobuf.internal::arena_delete_object
void arena_delete_object(void *object)
Definition: arena.h:99
google::protobuf::ArenaOptions::kDefaultMaxBlockSize
static const size_t kDefaultMaxBlockSize
Definition: arena.h:184
arena_impl.h
google::protobuf::ArenaOptions::Arena
friend class Arena
Definition: arena.h:187
Args
Args({7, 6, 3})
size
GLsizeiptr size
Definition: glcorearb.h:2943
std
google::protobuf.internal::arena_destruct_object
void arena_destruct_object(void *object)
Definition: arena.h:95
google::protobuf::ArenaOptions::block_dealloc
void(* block_dealloc)(void *, size_t)
Definition: arena.h:144
google::protobuf::arena_metrics::EnableArenaMetrics
void EnableArenaMetrics(ArenaOptions *options)
google::protobuf::ArenaOptions::max_block_size
size_t max_block_size
Definition: arena.h:124
google::protobuf::ArenaOptions::initial_block_size
size_t initial_block_size
Definition: arena.h:133
google::protobuf::alignas
class PROTOBUF_EXPORT alignas(8) Arena final
Definition: arena.h:248
google::protobuf.internal::arena_free
void arena_free(void *object, size_t size)
Definition: arena.h:102
google::protobuf::Map
Definition: map.h:62
internal
Definition: any.pb.h:40
google::protobuf.internal::GenericTypeHandler
Definition: arena.h:91
value
GLsizei const GLfloat * value
Definition: glcorearb.h:3093
google::protobuf::ArenaOptions::on_arena_reset
void(* on_arena_reset)(Arena *arena, void *cookie, uint64 space_used)
Definition: arena.h:170
google::protobuf::ArenaOptions::kDefaultStartBlockSize
static const size_t kDefaultStartBlockSize
Definition: arena.h:183
google
Definition: data_proto2_to_proto3_util.h:11
google::protobuf.internal::ArenaStringPtr
Definition: arenastring.h:68
benchmarks.python.py_benchmark.args
args
Definition: py_benchmark.py:24
google::protobuf.internal::ArenaImpl::kBlockHeaderSize
static const size_t kBlockHeaderSize
Definition: arena_impl.h:310
google::protobuf::ArenaOptions::on_arena_init
void *(* on_arena_init)(Arena *arena)
Definition: arena.h:169


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:48