Goby3  3.1.4
2024.02.22
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 #ifdef max
38 #undef max // Visual Studio defines this macro
39 #endif
40 #if defined(_MSC_VER) && !defined(_LIBCPP_STD_VER) && !_HAS_EXCEPTIONS
41 // Work around bugs in MSVC <typeinfo> header when _HAS_EXCEPTIONS=0.
42 #include <exception>
43 #include <typeinfo>
44 namespace std {
45 using type_info = ::type_info;
46 }
47 #else
48 #include <typeinfo>
49 #endif
50 
51 #include <google/protobuf/arena_impl.h>
52 #include <google/protobuf/stubs/port.h>
53 #include <type_traits>
54 
55 namespace google {
56 namespace protobuf {
57 
58 struct ArenaOptions; // defined below
59 
60 } // namespace protobuf
61 
62 namespace quality_webanswers {
63 
65 
66 } // namespace quality_webanswers
67 
68 namespace protobuf {
69 
70 class Arena; // defined below
71 class Message; // defined in message.h
72 class MessageLite;
73 
74 namespace arena_metrics {
75 
77 
78 } // namespace arena_metrics
79 
80 namespace internal {
81 
82 struct ArenaStringPtr; // defined in arenastring.h
83 class LazyField; // defined in lazy_field.h
84 
85 template <typename Type>
86 class GenericTypeHandler; // defined in repeated_field.h
87 
88 // Templated cleanup methods.
89 template <typename T>
90 void arena_destruct_object(void* object) {
91  reinterpret_cast<T*>(object)->~T();
92 }
93 template <typename T>
94 void arena_delete_object(void* object) {
95  delete reinterpret_cast<T*>(object);
96 }
97 inline void arena_free(void* object, size_t size) {
98 #if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation)
99  ::operator delete(object, size);
100 #else
101  (void)size;
102  ::operator delete(object);
103 #endif
104 }
105 
106 } // namespace internal
107 
108 // ArenaOptions provides optional additional parameters to arena construction
109 // that control its block-allocation behavior.
110 struct ArenaOptions {
111  // This defines the size of the first block requested from the system malloc.
112  // Subsequent block sizes will increase in a geometric series up to a maximum.
114 
115  // This defines the maximum block size requested from system malloc (unless an
116  // individual arena allocation request occurs with a size larger than this
117  // maximum). Requested block sizes increase up to this value, then remain
118  // here.
120 
121  // An initial block of memory for the arena to use, or NULL for none. If
122  // provided, the block must live at least as long as the arena itself. The
123  // creator of the Arena retains ownership of the block after the Arena is
124  // destroyed.
126 
127  // The size of the initial block, if provided.
129 
130  // A function pointer to an alloc method that returns memory blocks of size
131  // requested. By default, it contains a ptr to the malloc function.
132  //
133  // NOTE: block_alloc and dealloc functions are expected to behave like
134  // malloc and free, including Asan poisoning.
135  void* (*block_alloc)(size_t);
136  // A function pointer to a dealloc method that takes ownership of the blocks
137  // from the arena. By default, it contains a ptr to a wrapper function that
138  // calls free.
139  void (*block_dealloc)(void*, size_t);
140 
142  : start_block_size(kDefaultStartBlockSize),
143  max_block_size(kDefaultMaxBlockSize),
144  initial_block(NULL),
146  block_alloc(&::operator new),
147  block_dealloc(&internal::arena_free),
148  on_arena_init(NULL),
149  on_arena_reset(NULL),
150  on_arena_destruction(NULL),
151  on_arena_allocation(NULL) {}
152 
153  private:
154  // Hooks for adding external functionality such as user-specific metrics
155  // collection, specific debugging abilities, etc.
156  // Init hook may return a pointer to a cookie to be stored in the arena.
157  // reset and destruction hooks will then be called with the same cookie
158  // pointer. This allows us to save an external object per arena instance and
159  // use it on the other hooks (Note: It is just as legal for init to return
160  // NULL and not use the cookie feature).
161  // on_arena_reset and on_arena_destruction also receive the space used in
162  // the arena just before the reset.
163  void* (*on_arena_init)(Arena* arena);
164  void (*on_arena_reset)(Arena* arena, void* cookie, uint64 space_used);
165  void (*on_arena_destruction)(Arena* arena, void* cookie, uint64 space_used);
166 
167  // type_info is promised to be static - its lifetime extends to
168  // match program's lifetime (It is given by typeid operator).
169  // Note: typeid(void) will be passed as allocated_type every time we
170  // intentionally want to avoid monitoring an allocation. (i.e. internal
171  // allocations for managing the arena)
172  void (*on_arena_allocation)(const std::type_info* allocated_type,
173  uint64 alloc_size, void* cookie);
174 
175  // Constants define default starting block size and max block size for
176  // arena allocator behavior -- see descriptions above.
177  static const size_t kDefaultStartBlockSize = 256;
178  static const size_t kDefaultMaxBlockSize = 8192;
179 
182  friend class Arena;
184 };
185 
186 // Support for non-RTTI environments. (The metrics hooks API uses type
187 // information.)
188 #ifndef GOOGLE_PROTOBUF_NO_RTTI
189 #define RTTI_TYPE_ID(type) (&typeid(type))
190 #else
191 #define RTTI_TYPE_ID(type) (NULL)
192 #endif
193 
194 // Arena allocator. Arena allocation replaces ordinary (heap-based) allocation
195 // with new/delete, and improves performance by aggregating allocations into
196 // larger blocks and freeing allocations all at once. Protocol messages are
197 // allocated on an arena by using Arena::CreateMessage<T>(Arena*), below, and
198 // are automatically freed when the arena is destroyed.
199 //
200 // This is a thread-safe implementation: multiple threads may allocate from the
201 // arena concurrently. Destruction is not thread-safe and the destructing
202 // thread must synchronize with users of the arena first.
203 //
204 // An arena provides two allocation interfaces: CreateMessage<T>, which works
205 // for arena-enabled proto2 message types as well as other types that satisfy
206 // the appropriate protocol (described below), and Create<T>, which works for
207 // any arbitrary type T. CreateMessage<T> is better when the type T supports it,
208 // because this interface (i) passes the arena pointer to the created object so
209 // that its sub-objects and internal allocations can use the arena too, and (ii)
210 // elides the object's destructor call when possible. Create<T> does not place
211 // any special requirements on the type T, and will invoke the object's
212 // destructor when the arena is destroyed.
213 //
214 // The arena message allocation protocol, required by CreateMessage<T>, is as
215 // follows:
216 //
217 // - The type T must have (at least) two constructors: a constructor with no
218 // arguments, called when a T is allocated on the heap; and a constructor with
219 // a google::protobuf::Arena* argument, called when a T is allocated on an arena. If the
220 // second constructor is called with a NULL arena pointer, it must be
221 // equivalent to invoking the first (no-argument) constructor.
222 //
223 // - The type T must have a particular type trait: a nested type
224 // |InternalArenaConstructable_|. This is usually a typedef to |void|. If no
225 // such type trait exists, then the instantiation CreateMessage<T> will fail
226 // to compile.
227 //
228 // - The type T *may* have the type trait |DestructorSkippable_|. If this type
229 // trait is present in the type, then its destructor will not be called if and
230 // only if it was passed a non-NULL arena pointer. If this type trait is not
231 // present on the type, then its destructor is always called when the
232 // containing arena is destroyed.
233 //
234 // - One- and two-user-argument forms of CreateMessage<T>() also exist that
235 // forward these constructor arguments to T's constructor: for example,
236 // CreateMessage<T>(Arena*, arg1, arg2) forwards to a constructor T(Arena*,
237 // arg1, arg2).
238 //
239 // This protocol is implemented by all arena-enabled proto2 message classes as
240 // well as RepeatedPtrField.
241 //
242 // Do NOT subclass Arena. This class will be marked as final when C++11 is
243 // enabled.
244 class LIBPROTOBUF_EXPORT Arena {
245  public:
246  // Arena constructor taking custom options. See ArenaOptions below for
247  // descriptions of the options available.
248  explicit Arena(const ArenaOptions& options) : impl_(options) {
249  Init(options);
250  }
251 
252  // Block overhead. Use this as a guide for how much to over-allocate the
253  // initial block if you want an allocation of size N to fit inside it.
254  //
255  // WARNING: if you allocate multiple objects, it is difficult to guarantee
256  // that a series of allocations will fit in the initial block, especially if
257  // Arena changes its alignment guarantees in the future!
258  static const size_t kBlockOverhead = internal::ArenaImpl::kBlockHeaderSize +
259  internal::ArenaImpl::kSerialArenaSize;
260 
261  // Default constructor with sensible default options, tuned for average
262  // use-cases.
263  Arena() : impl_(ArenaOptions()) { Init(ArenaOptions()); }
264 
265  ~Arena() {
266  if (hooks_cookie_) {
267  CallDestructorHooks();
268  }
269  }
270 
271  void Init(const ArenaOptions& options) {
272  on_arena_allocation_ = options.on_arena_allocation;
273  on_arena_reset_ = options.on_arena_reset;
274  on_arena_destruction_ = options.on_arena_destruction;
275  // Call the initialization hook
276  if (options.on_arena_init != NULL) {
277  hooks_cookie_ = options.on_arena_init(this);
278  } else {
279  hooks_cookie_ = NULL;
280  }
281  }
282 
283  // API to create proto2 message objects on the arena. If the arena passed in
284  // is NULL, then a heap allocated object is returned. Type T must be a message
285  // defined in a .proto file with cc_enable_arenas set to true, otherwise a
286  // compilation error will occur.
287  //
288  // RepeatedField and RepeatedPtrField may also be instantiated directly on an
289  // arena with this method.
290  //
291  // This function also accepts any type T that satisfies the arena message
292  // allocation protocol, documented above.
293  template <typename T, typename... Args>
294  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateMessage(
295  Arena* arena, Args&&... args) {
296  static_assert(
298  "CreateMessage can only construct types that are ArenaConstructable");
299  // We must delegate to CreateMaybeMessage() and NOT CreateMessageInternal()
300  // because protobuf generated classes specialize CreateMaybeMessage() and we
301  // need to use that specialization for code size reasons.
302  return Arena::CreateMaybeMessage<T>(arena, std::forward<Args>(args)...);
303  }
304 
305  // API to create any objects on the arena. Note that only the object will
306  // be created on the arena; the underlying ptrs (in case of a proto2 message)
307  // will be still heap allocated. Proto messages should usually be allocated
308  // with CreateMessage<T>() instead.
309  //
310  // Note that even if T satisfies the arena message construction protocol
311  // (InternalArenaConstructable_ trait and optional DestructorSkippable_
312  // trait), as described above, this function does not follow the protocol;
313  // instead, it treats T as a black-box type, just as if it did not have these
314  // traits. Specifically, T's constructor arguments will always be only those
315  // passed to Create<T>() -- no additional arena pointer is implicitly added.
316  // Furthermore, the destructor will always be called at arena destruction time
317  // (unless the destructor is trivial). Hence, from T's point of view, it is as
318  // if the object were allocated on the heap (except that the underlying memory
319  // is obtained from the arena).
320  template <typename T, typename... Args>
321  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* Create(Arena* arena,
322  Args&&... args) {
323  return CreateNoMessage<T>(arena, is_arena_constructable<T>(),
324  std::forward<Args>(args)...);
325  }
326 
327  // Create an array of object type T on the arena *without* invoking the
328  // constructor of T. If `arena` is null, then the return value should be freed
329  // with `delete[] x;` (or `::operator delete[](x);`).
330  // To ensure safe uses, this function checks at compile time
331  // (when compiled as C++11) that T is trivially default-constructible and
332  // trivially destructible.
333  template <typename T>
334  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateArray(
335  Arena* arena, size_t num_elements) {
336  static_assert(std::is_pod<T>::value,
337  "CreateArray requires a trivially constructible type");
338  static_assert(std::is_trivially_destructible<T>::value,
339  "CreateArray requires a trivially destructible type");
340  GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
341  << "Requested size is too large to fit into size_t.";
342  if (arena == NULL) {
343  return static_cast<T*>(::operator new[](num_elements * sizeof(T)));
344  } else {
345  return arena->CreateInternalRawArray<T>(num_elements);
346  }
347  }
348 
349  // Returns the total space allocated by the arena, which is the sum of the
350  // sizes of the underlying blocks. This method is relatively fast; a counter
351  // is kept as blocks are allocated.
352  uint64 SpaceAllocated() const { return impl_.SpaceAllocated(); }
353  // Returns the total space used by the arena. Similar to SpaceAllocated but
354  // does not include free space and block overhead. The total space returned
355  // may not include space used by other threads executing concurrently with
356  // the call to this method.
357  uint64 SpaceUsed() const { return impl_.SpaceUsed(); }
358  // DEPRECATED. Please use SpaceAllocated() and SpaceUsed().
359  //
360  // Combines SpaceAllocated and SpaceUsed. Returns a pair of
361  // <space_allocated, space_used>.
362  PROTOBUF_RUNTIME_DEPRECATED("Please use SpaceAllocated() and SpaceUsed()")
363  std::pair<uint64, uint64> SpaceAllocatedAndUsed() const {
364  return std::make_pair(SpaceAllocated(), SpaceUsed());
365  }
366 
367  // Frees all storage allocated by this arena after calling destructors
368  // registered with OwnDestructor() and freeing objects registered with Own().
369  // Any objects allocated on this arena are unusable after this call. It also
370  // returns the total space used by the arena which is the sums of the sizes
371  // of the allocated blocks. This method is not thread-safe.
372  GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE uint64 Reset() {
373  // Call the reset hook
374  if (on_arena_reset_ != NULL) {
375  on_arena_reset_(this, hooks_cookie_, impl_.SpaceAllocated());
376  }
377  return impl_.Reset();
378  }
379 
380  // Adds |object| to a list of heap-allocated objects to be freed with |delete|
381  // when the arena is destroyed or reset.
382  template <typename T>
383  GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE void Own(T* object) {
384  OwnInternal(object, std::is_convertible<T*, Message*>());
385  }
386 
387  // Adds |object| to a list of objects whose destructors will be manually
388  // called when the arena is destroyed or reset. This differs from Own() in
389  // that it does not free the underlying memory with |delete|; hence, it is
390  // normally only used for objects that are placement-newed into
391  // arena-allocated memory.
392  template <typename T>
393  GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE void OwnDestructor(T* object) {
394  if (object != NULL) {
395  impl_.AddCleanup(object, &internal::arena_destruct_object<T>);
396  }
397  }
398 
399  // Adds a custom member function on an object to the list of destructors that
400  // will be manually called when the arena is destroyed or reset. This differs
401  // from OwnDestructor() in that any member function may be specified, not only
402  // the class destructor.
403  GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE void OwnCustomDestructor(
404  void* object, void (*destruct)(void*)) {
405  impl_.AddCleanup(object, destruct);
406  }
407 
408  // Retrieves the arena associated with |value| if |value| is an arena-capable
409  // message, or NULL otherwise. This differs from value->GetArena() in that the
410  // latter is a virtual call, while this method is a templated call that
411  // resolves at compile-time.
412  template <typename T>
413  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static Arena* GetArena(
414  const T* value) {
415  return GetArenaInternal(value, is_arena_constructable<T>());
416  }
417 
418  template <typename T>
420  template <typename U>
421  static char DestructorSkippable(const typename U::DestructorSkippable_*);
422  template <typename U>
423  static double DestructorSkippable(...);
424 
425  typedef std::integral_constant<
426  bool, sizeof(DestructorSkippable<T>(static_cast<const T*>(0))) ==
427  sizeof(char) ||
428  std::is_trivially_destructible<T>::value>
429  is_destructor_skippable;
430 
431  template <typename U>
432  static char ArenaConstructable(
433  const typename U::InternalArenaConstructable_*);
434  template <typename U>
435  static double ArenaConstructable(...);
436 
437  typedef std::integral_constant<bool, sizeof(ArenaConstructable<T>(
438  static_cast<const T*>(0))) ==
439  sizeof(char)>
440  is_arena_constructable;
441 
442  template <typename... Args>
443  static T* Construct(void* ptr, Args&&... args) {
444  return new (ptr) T(std::forward<Args>(args)...);
445  }
446 
447  static Arena* GetArena(const T* p) { return p->GetArenaNoVirtual(); }
448 
449  friend class Arena;
450  };
451 
452  // Helper typetraits that indicates support for arenas in a type T at compile
453  // time. This is public only to allow construction of higher-level templated
454  // utilities.
455  //
456  // is_arena_constructable<T>::value is true if the message type T has arena
457  // support enabled, and false otherwise.
458  //
459  // is_destructor_skippable<T>::value is true if the message type T has told
460  // the arena that it is safe to skip the destructor, and false otherwise.
461  //
462  // This is inside Arena because only Arena has the friend relationships
463  // necessary to see the underlying generated code traits.
464  template <typename T>
466  template <typename T>
468  };
469 
470  private:
471  template <typename T, typename... Args>
472  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateMessageInternal(
473  Arena* arena, Args&&... args) {
474  static_assert(
476  "CreateMessage can only construct types that are ArenaConstructable");
477  if (arena == NULL) {
478  return new T(nullptr, std::forward<Args>(args)...);
479  } else {
480  return arena->DoCreateMessage<T>(std::forward<Args>(args)...);
481  }
482  }
483 
484  // This specialization for no arguments is necessary, because its behavior is
485  // slightly different. When the arena pointer is nullptr, it calls T()
486  // instead of T(nullptr).
487  template <typename T>
488  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateMessageInternal(
489  Arena* arena) {
490  static_assert(
491  InternalHelper<T>::is_arena_constructable::value,
492  "CreateMessage can only construct types that are ArenaConstructable");
493  if (arena == NULL) {
494  return new T();
495  } else {
496  return arena->DoCreateMessage<T>();
497  }
498  }
499 
500  template <typename T, typename... Args>
501  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateInternal(
502  Arena* arena, Args&&... args) {
503  if (arena == NULL) {
504  return new T(std::forward<Args>(args)...);
505  } else {
506  return arena->DoCreate<T>(std::is_trivially_destructible<T>::value,
507  std::forward<Args>(args)...);
508  }
509  }
510 
511  void CallDestructorHooks();
512  void OnArenaAllocation(const std::type_info* allocated_type, size_t n) const;
513  inline void AllocHook(const std::type_info* allocated_type, size_t n) const {
514  if (GOOGLE_PREDICT_FALSE(hooks_cookie_ != NULL)) {
515  OnArenaAllocation(allocated_type, n);
516  }
517  }
518 
519  // Allocate and also optionally call on_arena_allocation callback with the
520  // allocated type info when the hooks are in place in ArenaOptions and
521  // the cookie is not null.
522  template <typename T>
523  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void* AllocateInternal(
524  bool skip_explicit_ownership) {
525  const size_t n = internal::AlignUpTo8(sizeof(T));
526  AllocHook(RTTI_TYPE_ID(T), n);
527  // Monitor allocation if needed.
528  if (skip_explicit_ownership) {
529  return impl_.AllocateAligned(n);
530  } else {
531  return impl_.AllocateAlignedAndAddCleanup(
532  n, &internal::arena_destruct_object<T>);
533  }
534  }
535 
536  // CreateMessage<T> requires that T supports arenas, but this private method
537  // works whether or not T supports arenas. These are not exposed to user code
538  // as it can cause confusing API usages, and end up having double free in
539  // user code. These are used only internally from LazyField and Repeated
540  // fields, since they are designed to work in all mode combinations.
541  template <typename Msg, typename... Args>
542  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static Msg* DoCreateMaybeMessage(
543  Arena* arena, std::true_type, Args&&... args) {
544  return CreateMessageInternal<Msg>(arena, std::forward<Args>(args)...);
545  }
546 
547  template <typename T, typename... Args>
548  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* DoCreateMaybeMessage(
549  Arena* arena, std::false_type, Args&&... args) {
550  return CreateInternal<T>(arena, std::forward<Args>(args)...);
551  }
552 
553  template <typename T, typename... Args>
554  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateMaybeMessage(
555  Arena* arena, Args&&... args) {
556  return DoCreateMaybeMessage<T>(arena, is_arena_constructable<T>(),
557  std::forward<Args>(args)...);
558  }
559 
560  template <typename T, typename... Args>
561  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateNoMessage(
562  Arena* arena, std::true_type, Args&&... args) {
563  // User is constructing with Create() despite the fact that T supports arena
564  // construction. In this case we have to delegate to CreateInternal(), and
565  // we can't use any CreateMaybeMessage() specialization that may be defined.
566  return CreateInternal<T>(arena, std::forward<Args>(args)...);
567  }
568 
569  template <typename T, typename... Args>
570  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static T* CreateNoMessage(
571  Arena* arena, std::false_type, Args&&... args) {
572  // User is constructing with Create() and the type does not support arena
573  // construction. In this case we can delegate to CreateMaybeMessage() and
574  // use any specialization that may be available for that.
575  return CreateMaybeMessage<T>(arena, std::forward<Args>(args)...);
576  }
577 
578  // Just allocate the required size for the given type assuming the
579  // type has a trivial constructor.
580  template <typename T>
581  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T* CreateInternalRawArray(
582  size_t num_elements) {
583  GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
584  << "Requested size is too large to fit into size_t.";
585  const size_t n = internal::AlignUpTo8(sizeof(T) * num_elements);
586  // Monitor allocation if needed.
587  AllocHook(RTTI_TYPE_ID(T), n);
588  return static_cast<T*>(impl_.AllocateAligned(n));
589  }
590 
591  template <typename T, typename... Args>
592  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T* DoCreate(
593  bool skip_explicit_ownership, Args&&... args) {
594  return new (AllocateInternal<T>(skip_explicit_ownership))
595  T(std::forward<Args>(args)...);
596  }
597  template <typename T, typename... Args>
598  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T* DoCreateMessage(Args&&... args) {
599  return InternalHelper<T>::Construct(
600  AllocateInternal<T>(InternalHelper<T>::is_destructor_skippable::value),
601  this, std::forward<Args>(args)...);
602  }
603 
604  // CreateInArenaStorage is used to implement map field. Without it,
605  // google::protobuf::Map need to call generated message's protected arena constructor,
606  // which needs to declare google::protobuf::Map as friend of generated message.
607  template <typename T>
608  static void CreateInArenaStorage(T* ptr, Arena* arena) {
609  CreateInArenaStorageInternal(ptr, arena,
611  RegisterDestructorInternal(
612  ptr, arena,
614  }
615 
616  template <typename T>
617  static void CreateInArenaStorageInternal(T* ptr, Arena* arena,
618  std::true_type) {
619  InternalHelper<T>::Construct(ptr, arena);
620  }
621  template <typename T>
622  static void CreateInArenaStorageInternal(T* ptr, Arena* /* arena */,
623  std::false_type) {
624  new (ptr) T();
625  }
626 
627  template <typename T>
628  static void RegisterDestructorInternal(T* /* ptr */, Arena* /* arena */,
629  std::true_type) {}
630  template <typename T>
631  static void RegisterDestructorInternal(T* ptr, Arena* arena,
632  std::false_type) {
633  arena->OwnDestructor(ptr);
634  }
635 
636  // These implement Own(), which registers an object for deletion (destructor
637  // call and operator delete()). The second parameter has type 'true_type' if T
638  // is a subtype of ::google::protobuf::Message and 'false_type' otherwise. Collapsing
639  // all template instantiations to one for generic Message reduces code size,
640  // using the virtual destructor instead.
641  template <typename T>
642  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void OwnInternal(T* object,
643  std::true_type) {
644  if (object != NULL) {
645  impl_.AddCleanup(object, &internal::arena_delete_object<Message>);
646  }
647  }
648  template <typename T>
649  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE void OwnInternal(T* object,
650  std::false_type) {
651  if (object != NULL) {
652  impl_.AddCleanup(object, &internal::arena_delete_object<T>);
653  }
654  }
655 
656  // Implementation for GetArena(). Only message objects with
657  // InternalArenaConstructable_ tags can be associated with an arena, and such
658  // objects must implement a GetArenaNoVirtual() method.
659  template <typename T>
660  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static Arena* GetArenaInternal(
661  const T* value, std::true_type) {
662  return InternalHelper<T>::GetArena(value);
663  }
664 
665  template <typename T>
666  GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE static Arena* GetArenaInternal(
667  const T* /* value */, std::false_type) {
668  return NULL;
669  }
670 
671  // For friends of arena.
672  void* AllocateAligned(size_t n) {
673  AllocHook(NULL, n);
674  return impl_.AllocateAligned(internal::AlignUpTo8(n));
675  }
676 
677  internal::ArenaImpl impl_;
678 
679  void (*on_arena_allocation_)(const std::type_info* allocated_type,
680  uint64 alloc_size, void* cookie);
681  void (*on_arena_reset_)(Arena* arena, void* cookie, uint64 space_used);
682  void (*on_arena_destruction_)(Arena* arena, void* cookie, uint64 space_used);
683 
684  // The arena may save a cookie it receives from the external on_init hook
685  // and then use it when calling the on_reset and on_destruction hooks.
686  void* hooks_cookie_;
687 
688  template <typename Type>
690  friend struct internal::ArenaStringPtr; // For AllocateAligned.
691  friend class internal::LazyField; // For CreateMaybeMessage.
692  friend class MessageLite;
693  template <typename Key, typename T>
694  friend class Map;
695 };
696 
697 // Defined above for supporting environments without RTTI.
698 #undef RTTI_TYPE_ID
699 
700 } // namespace protobuf
701 
702 } // namespace google
703 #endif // GOOGLE_PROTOBUF_ARENA_H__
google::protobuf::ArenaOptions::ArenaOptions
ArenaOptions()
Definition: arena.h:141
google::protobuf::Arena::is_arena_constructable
Definition: arena.h:465
google::protobuf::Arena::Arena
Arena(const ArenaOptions &options)
Definition: arena.h:248
google::protobuf::Arena::OwnCustomDestructor
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE void OwnCustomDestructor(void *object, void(*destruct)(void *))
Definition: arena.h:403
google::protobuf::Arena::Create
static GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T * Create(Arena *arena, Args &&... args)
Definition: arena.h:321
goby::uint64
std::uint64_t uint64
Definition: primitive_types.h:34
google::protobuf::ArenaOptions::block_alloc
void *(* block_alloc)(size_t)
Definition: arena.h:135
google::protobuf::MessageLite
Definition: message_lite.h:164
google::protobuf::ArenaOptions::start_block_size
size_t start_block_size
Definition: arena.h:113
google::protobuf::Arena::CreateArray
static GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T * CreateArray(Arena *arena, size_t num_elements)
Definition: arena.h:334
google::protobuf::Arena
Definition: arena.h:244
detail::void
j template void())
Definition: json.hpp:4822
bool
RTTI_TYPE_ID
#define RTTI_TYPE_ID(type)
Definition: arena.h:189
google::protobuf::Arena::~Arena
~Arena()
Definition: arena.h:265
google::protobuf::ArenaOptions::ArenaOptionsTestFriend
friend class ArenaOptionsTestFriend
Definition: arena.h:183
google::protobuf::ArenaOptions::initial_block
char * initial_block
Definition: arena.h:125
google::protobuf::Arena::OwnDestructor
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE void OwnDestructor(T *object)
Definition: arena.h:393
google::protobuf::Arena::CreateMessage
static GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE T * CreateMessage(Arena *arena, Args &&... args)
Definition: arena.h:294
google::protobuf::Arena::GetArena
static GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE Arena * GetArena(const T *value)
Definition: arena.h:413
google::protobuf::Arena::Own
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE void Own(T *object)
Definition: arena.h:383
google::protobuf::Arena::Init
void Init(const ArenaOptions &options)
Definition: arena.h:271
jwt::json::type
type
Generic JSON types used in JWTs.
Definition: jwt.h:2071
google::protobuf::Arena::InternalHelper
Definition: arena.h:419
google::protobuf::ArenaOptions
Definition: arena.h:110
google::protobuf::Arena::Arena
Arena()
Definition: arena.h:263
google::protobuf::internal::arena_delete_object
void arena_delete_object(void *object)
Definition: arena.h:94
google::protobuf::Arena::PROTOBUF_RUNTIME_DEPRECATED
PROTOBUF_RUNTIME_DEPRECATED("Please use SpaceAllocated() and SpaceUsed()") std
Definition: arena.h:362
google::quality_webanswers::TempPrivateWorkAround
void TempPrivateWorkAround(::google::protobuf::ArenaOptions *arena_options)
google::protobuf::Arena::is_destructor_skippable
Definition: arena.h:467
google::protobuf::internal::arena_destruct_object
void arena_destruct_object(void *object)
Definition: arena.h:90
google::protobuf::ArenaOptions::block_dealloc
void(* block_dealloc)(void *, size_t)
Definition: arena.h:139
google::protobuf::ArenaOptions::max_block_size
size_t max_block_size
Definition: arena.h:119
google::protobuf::ArenaOptions::initial_block_size
size_t initial_block_size
Definition: arena.h:128
google::protobuf::Arena::SpaceAllocated
uint64 SpaceAllocated() const
Definition: arena.h:352
google::protobuf::internal::arena_free
void arena_free(void *object, size_t size)
Definition: arena.h:97
google::protobuf::internal::GenericTypeHandler
Definition: arena.h:86
google::protobuf::arena_metrics::EnableArenaMetrics
void EnableArenaMetrics(::google::protobuf::ArenaOptions *options)
google::protobuf::Arena::SpaceUsed
uint64 SpaceUsed() const
Definition: arena.h:357
google
Definition: dccl.h:57