You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

arena.h 36 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851
  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. // This file defines an Arena allocator for better allocation performance.
  31. #ifndef GOOGLE_PROTOBUF_ARENA_H__
  32. #define GOOGLE_PROTOBUF_ARENA_H__
  33. #include <limits>
  34. #include <type_traits>
  35. #include <utility>
  36. #if defined(_MSC_VER) && !defined(_LIBCPP_STD_VER) && !_HAS_EXCEPTIONS
  37. // Work around bugs in MSVC <typeinfo> header when _HAS_EXCEPTIONS=0.
  38. #include <exception>
  39. #include <typeinfo>
  40. namespace std {
  41. using type_info = ::type_info;
  42. }
  43. #else
  44. #include <typeinfo>
  45. #endif
  46. #include <type_traits>
  47. #include <google/protobuf/arena_impl.h>
  48. #include <google/protobuf/port.h>
  49. // Must be included last.
  50. #include <google/protobuf/port_def.inc>
  51. #ifdef SWIG
  52. #error "You cannot SWIG proto headers"
  53. #endif
  54. namespace google {
  55. namespace protobuf {
  56. struct ArenaOptions; // defined below
  57. class Arena; // defined below
  58. class Message; // defined in message.h
  59. class MessageLite;
  60. template <typename Key, typename T>
  61. class Map;
  62. namespace arena_metrics {
  63. void EnableArenaMetrics(ArenaOptions* options);
  64. } // namespace arena_metrics
  65. namespace TestUtil {
  66. class ReflectionTester; // defined in test_util.h
  67. } // namespace TestUtil
  68. namespace internal {
  69. struct ArenaTestPeer; // defined in arena_test_util.h
  70. class InternalMetadata; // defined in metadata_lite.h
  71. class LazyField; // defined in lazy_field.h
  72. class EpsCopyInputStream; // defined in parse_context.h
  73. class RepeatedPtrFieldBase; // defined in repeated_ptr_field.h
  74. template <typename Type>
  75. class GenericTypeHandler; // defined in repeated_field.h
  76. inline PROTOBUF_ALWAYS_INLINE
  77. void* AlignTo(void* ptr, size_t align) {
  78. return reinterpret_cast<void*>(
  79. (reinterpret_cast<uintptr_t>(ptr) + align - 1) & (~align + 1));
  80. }
  81. // Templated cleanup methods.
  82. template <typename T>
  83. void arena_destruct_object(void* object) {
  84. reinterpret_cast<T*>(object)->~T();
  85. }
  86. template <bool destructor_skippable, typename T>
  87. struct ObjectDestructor {
  88. constexpr static void (*destructor)(void*) = &arena_destruct_object<T>;
  89. };
  90. template <typename T>
  91. struct ObjectDestructor<true, T> {
  92. constexpr static void (*destructor)(void*) = nullptr;
  93. };
  94. template <typename T>
  95. void arena_delete_object(void* object) {
  96. delete reinterpret_cast<T*>(object);
  97. }
  98. } // namespace internal
  99. // ArenaOptions provides optional additional parameters to arena construction
  100. // that control its block-allocation behavior.
  101. struct ArenaOptions {
  102. // This defines the size of the first block requested from the system malloc.
  103. // Subsequent block sizes will increase in a geometric series up to a maximum.
  104. size_t start_block_size;
  105. // This defines the maximum block size requested from system malloc (unless an
  106. // individual arena allocation request occurs with a size larger than this
  107. // maximum). Requested block sizes increase up to this value, then remain
  108. // here.
  109. size_t max_block_size;
  110. // An initial block of memory for the arena to use, or NULL for none. If
  111. // provided, the block must live at least as long as the arena itself. The
  112. // creator of the Arena retains ownership of the block after the Arena is
  113. // destroyed.
  114. char* initial_block;
  115. // The size of the initial block, if provided.
  116. size_t initial_block_size;
  117. // A function pointer to an alloc method that returns memory blocks of size
  118. // requested. By default, it contains a ptr to the malloc function.
  119. //
  120. // NOTE: block_alloc and dealloc functions are expected to behave like
  121. // malloc and free, including Asan poisoning.
  122. void* (*block_alloc)(size_t);
  123. // A function pointer to a dealloc method that takes ownership of the blocks
  124. // from the arena. By default, it contains a ptr to a wrapper function that
  125. // calls free.
  126. void (*block_dealloc)(void*, size_t);
  127. ArenaOptions()
  128. : start_block_size(internal::AllocationPolicy::kDefaultStartBlockSize),
  129. max_block_size(internal::AllocationPolicy::kDefaultMaxBlockSize),
  130. initial_block(NULL),
  131. initial_block_size(0),
  132. block_alloc(nullptr),
  133. block_dealloc(nullptr),
  134. make_metrics_collector(nullptr) {}
  135. private:
  136. // If make_metrics_collector is not nullptr, it will be called at Arena init
  137. // time. It may return a pointer to a collector instance that will be notified
  138. // of interesting events related to the arena.
  139. internal::ArenaMetricsCollector* (*make_metrics_collector)();
  140. internal::ArenaMetricsCollector* MetricsCollector() const {
  141. return make_metrics_collector ? (*make_metrics_collector)() : nullptr;
  142. }
  143. internal::AllocationPolicy AllocationPolicy() const {
  144. internal::AllocationPolicy res;
  145. res.start_block_size = start_block_size;
  146. res.max_block_size = max_block_size;
  147. res.block_alloc = block_alloc;
  148. res.block_dealloc = block_dealloc;
  149. res.metrics_collector = MetricsCollector();
  150. return res;
  151. }
  152. friend void arena_metrics::EnableArenaMetrics(ArenaOptions*);
  153. friend class Arena;
  154. friend class ArenaOptionsTestFriend;
  155. };
  156. // Support for non-RTTI environments. (The metrics hooks API uses type
  157. // information.)
  158. #if PROTOBUF_RTTI
  159. #define RTTI_TYPE_ID(type) (&typeid(type))
  160. #else
  161. #define RTTI_TYPE_ID(type) (NULL)
  162. #endif
  163. // Arena allocator. Arena allocation replaces ordinary (heap-based) allocation
  164. // with new/delete, and improves performance by aggregating allocations into
  165. // larger blocks and freeing allocations all at once. Protocol messages are
  166. // allocated on an arena by using Arena::CreateMessage<T>(Arena*), below, and
  167. // are automatically freed when the arena is destroyed.
  168. //
  169. // This is a thread-safe implementation: multiple threads may allocate from the
  170. // arena concurrently. Destruction is not thread-safe and the destructing
  171. // thread must synchronize with users of the arena first.
  172. //
  173. // An arena provides two allocation interfaces: CreateMessage<T>, which works
  174. // for arena-enabled proto2 message types as well as other types that satisfy
  175. // the appropriate protocol (described below), and Create<T>, which works for
  176. // any arbitrary type T. CreateMessage<T> is better when the type T supports it,
  177. // because this interface (i) passes the arena pointer to the created object so
  178. // that its sub-objects and internal allocations can use the arena too, and (ii)
  179. // elides the object's destructor call when possible. Create<T> does not place
  180. // any special requirements on the type T, and will invoke the object's
  181. // destructor when the arena is destroyed.
  182. //
  183. // The arena message allocation protocol, required by
  184. // CreateMessage<T>(Arena* arena, Args&&... args), is as follows:
  185. //
  186. // - The type T must have (at least) two constructors: a constructor callable
  187. // with `args` (without `arena`), called when a T is allocated on the heap;
  188. // and a constructor callable with `Arena* arena, Args&&... args`, called when
  189. // a T is allocated on an arena. If the second constructor is called with a
  190. // NULL arena pointer, it must be equivalent to invoking the first
  191. // (`args`-only) constructor.
  192. //
  193. // - The type T must have a particular type trait: a nested type
  194. // |InternalArenaConstructable_|. This is usually a typedef to |void|. If no
  195. // such type trait exists, then the instantiation CreateMessage<T> will fail
  196. // to compile.
  197. //
  198. // - The type T *may* have the type trait |DestructorSkippable_|. If this type
  199. // trait is present in the type, then its destructor will not be called if and
  200. // only if it was passed a non-NULL arena pointer. If this type trait is not
  201. // present on the type, then its destructor is always called when the
  202. // containing arena is destroyed.
  203. //
  204. // This protocol is implemented by all arena-enabled proto2 message classes as
  205. // well as protobuf container types like RepeatedPtrField and Map. The protocol
  206. // is internal to protobuf and is not guaranteed to be stable. Non-proto types
  207. // should not rely on this protocol.
  208. class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
  209. public:
  210. // Default constructor with sensible default options, tuned for average
  211. // use-cases.
  212. inline Arena() : impl_() {}
  213. // Construct an arena with default options, except for the supplied
  214. // initial block. It is more efficient to use this constructor
  215. // instead of passing ArenaOptions if the only configuration needed
  216. // by the caller is supplying an initial block.
  217. inline Arena(char* initial_block, size_t initial_block_size)
  218. : impl_(initial_block, initial_block_size) {}
  219. // Arena constructor taking custom options. See ArenaOptions above for
  220. // descriptions of the options available.
  221. explicit Arena(const ArenaOptions& options)
  222. : impl_(options.initial_block, options.initial_block_size,
  223. options.AllocationPolicy()) {}
  224. // Block overhead. Use this as a guide for how much to over-allocate the
  225. // initial block if you want an allocation of size N to fit inside it.
  226. //
  227. // WARNING: if you allocate multiple objects, it is difficult to guarantee
  228. // that a series of allocations will fit in the initial block, especially if
  229. // Arena changes its alignment guarantees in the future!
  230. static const size_t kBlockOverhead =
  231. internal::ThreadSafeArena::kBlockHeaderSize +
  232. internal::ThreadSafeArena::kSerialArenaSize;
  233. inline ~Arena() {}
  234. // TODO(protobuf-team): Fix callers to use constructor and delete this method.
  235. void Init(const ArenaOptions&) {}
  236. // API to create proto2 message objects on the arena. If the arena passed in
  237. // is NULL, then a heap allocated object is returned. Type T must be a message
  238. // defined in a .proto file with cc_enable_arenas set to true, otherwise a
  239. // compilation error will occur.
  240. //
  241. // RepeatedField and RepeatedPtrField may also be instantiated directly on an
  242. // arena with this method.
  243. //
  244. // This function also accepts any type T that satisfies the arena message
  245. // allocation protocol, documented above.
  246. template <typename T, typename... Args>
  247. PROTOBUF_ALWAYS_INLINE static T* CreateMessage(Arena* arena, Args&&... args) {
  248. static_assert(
  249. InternalHelper<T>::is_arena_constructable::value,
  250. "CreateMessage can only construct types that are ArenaConstructable");
  251. // We must delegate to CreateMaybeMessage() and NOT CreateMessageInternal()
  252. // because protobuf generated classes specialize CreateMaybeMessage() and we
  253. // need to use that specialization for code size reasons.
  254. return Arena::CreateMaybeMessage<T>(arena, static_cast<Args&&>(args)...);
  255. }
  256. // API to create any objects on the arena. Note that only the object will
  257. // be created on the arena; the underlying ptrs (in case of a proto2 message)
  258. // will be still heap allocated. Proto messages should usually be allocated
  259. // with CreateMessage<T>() instead.
  260. //
  261. // Note that even if T satisfies the arena message construction protocol
  262. // (InternalArenaConstructable_ trait and optional DestructorSkippable_
  263. // trait), as described above, this function does not follow the protocol;
  264. // instead, it treats T as a black-box type, just as if it did not have these
  265. // traits. Specifically, T's constructor arguments will always be only those
  266. // passed to Create<T>() -- no additional arena pointer is implicitly added.
  267. // Furthermore, the destructor will always be called at arena destruction time
  268. // (unless the destructor is trivial). Hence, from T's point of view, it is as
  269. // if the object were allocated on the heap (except that the underlying memory
  270. // is obtained from the arena).
  271. template <typename T, typename... Args>
  272. PROTOBUF_NDEBUG_INLINE static T* Create(Arena* arena, Args&&... args) {
  273. return CreateInternal<T>(arena, std::is_convertible<T*, MessageLite*>(),
  274. static_cast<Args&&>(args)...);
  275. }
  276. // Allocates memory with the specific size and alignment.
  277. void* AllocateAligned(size_t size, size_t align = 8) {
  278. if (align <= 8) {
  279. return AllocateAlignedNoHook(internal::AlignUpTo8(size));
  280. } else {
  281. // We are wasting space by over allocating align - 8 bytes. Compared
  282. // to a dedicated function that takes current alignment in consideration.
  283. // Such a scheme would only waste (align - 8)/2 bytes on average, but
  284. // requires a dedicated function in the outline arena allocation
  285. // functions. Possibly re-evaluate tradeoffs later.
  286. return internal::AlignTo(AllocateAlignedNoHook(size + align - 8), align);
  287. }
  288. }
  289. // Create an array of object type T on the arena *without* invoking the
  290. // constructor of T. If `arena` is null, then the return value should be freed
  291. // with `delete[] x;` (or `::operator delete[](x);`).
  292. // To ensure safe uses, this function checks at compile time
  293. // (when compiled as C++11) that T is trivially default-constructible and
  294. // trivially destructible.
  295. template <typename T>
  296. PROTOBUF_NDEBUG_INLINE static T* CreateArray(Arena* arena,
  297. size_t num_elements) {
  298. static_assert(std::is_trivial<T>::value,
  299. "CreateArray requires a trivially constructible type");
  300. static_assert(std::is_trivially_destructible<T>::value,
  301. "CreateArray requires a trivially destructible type");
  302. GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
  303. << "Requested size is too large to fit into size_t.";
  304. if (arena == NULL) {
  305. return static_cast<T*>(::operator new[](num_elements * sizeof(T)));
  306. } else {
  307. return arena->CreateInternalRawArray<T>(num_elements);
  308. }
  309. }
  310. // The following are routines are for monitoring. They will approximate the
  311. // total sum allocated and used memory, but the exact value is an
  312. // implementation deal. For instance allocated space depends on growth
  313. // policies. Do not use these in unit tests.
  314. // Returns the total space allocated by the arena, which is the sum of the
  315. // sizes of the underlying blocks.
  316. uint64_t SpaceAllocated() const { return impl_.SpaceAllocated(); }
  317. // Returns the total space used by the arena. Similar to SpaceAllocated but
  318. // does not include free space and block overhead. The total space returned
  319. // may not include space used by other threads executing concurrently with
  320. // the call to this method.
  321. uint64_t SpaceUsed() const { return impl_.SpaceUsed(); }
  322. // Frees all storage allocated by this arena after calling destructors
  323. // registered with OwnDestructor() and freeing objects registered with Own().
  324. // Any objects allocated on this arena are unusable after this call. It also
  325. // returns the total space used by the arena which is the sums of the sizes
  326. // of the allocated blocks. This method is not thread-safe.
  327. uint64_t Reset() { return impl_.Reset(); }
  328. // Adds |object| to a list of heap-allocated objects to be freed with |delete|
  329. // when the arena is destroyed or reset.
  330. template <typename T>
  331. PROTOBUF_ALWAYS_INLINE void Own(T* object) {
  332. OwnInternal(object, std::is_convertible<T*, MessageLite*>());
  333. }
  334. // Adds |object| to a list of objects whose destructors will be manually
  335. // called when the arena is destroyed or reset. This differs from Own() in
  336. // that it does not free the underlying memory with |delete|; hence, it is
  337. // normally only used for objects that are placement-newed into
  338. // arena-allocated memory.
  339. template <typename T>
  340. PROTOBUF_ALWAYS_INLINE void OwnDestructor(T* object) {
  341. if (object != NULL) {
  342. impl_.AddCleanup(object, &internal::arena_destruct_object<T>);
  343. }
  344. }
  345. // Adds a custom member function on an object to the list of destructors that
  346. // will be manually called when the arena is destroyed or reset. This differs
  347. // from OwnDestructor() in that any member function may be specified, not only
  348. // the class destructor.
  349. PROTOBUF_ALWAYS_INLINE void OwnCustomDestructor(void* object,
  350. void (*destruct)(void*)) {
  351. impl_.AddCleanup(object, destruct);
  352. }
  353. // Retrieves the arena associated with |value| if |value| is an arena-capable
  354. // message, or NULL otherwise. If possible, the call resolves at compile time.
  355. // Note that we can often devirtualize calls to `value->GetArena()` so usually
  356. // calling this method is unnecessary.
  357. template <typename T>
  358. PROTOBUF_ALWAYS_INLINE static Arena* GetArena(const T* value) {
  359. return GetArenaInternal(value);
  360. }
  361. template <typename T>
  362. class InternalHelper {
  363. private:
  364. // Provides access to protected GetOwningArena to generated messages.
  365. static Arena* GetOwningArena(const T* p) { return p->GetOwningArena(); }
  366. static void InternalSwap(T* a, T* b) { a->InternalSwap(b); }
  367. static Arena* GetArenaForAllocationInternal(
  368. const T* p, std::true_type /*is_derived_from<MessageLite>*/) {
  369. return p->GetArenaForAllocation();
  370. }
  371. static Arena* GetArenaForAllocationInternal(
  372. const T* p, std::false_type /*is_derived_from<MessageLite>*/) {
  373. return GetArenaForAllocationForNonMessage(
  374. p, typename is_arena_constructable::type());
  375. }
  376. static Arena* GetArenaForAllocationForNonMessage(
  377. const T* p, std::true_type /*is_arena_constructible*/) {
  378. return p->GetArena();
  379. }
  380. static Arena* GetArenaForAllocationForNonMessage(
  381. const T* p, std::false_type /*is_arena_constructible*/) {
  382. return GetArenaForAllocationForNonMessageNonArenaConstructible(
  383. p, typename has_get_arena::type());
  384. }
  385. static Arena* GetArenaForAllocationForNonMessageNonArenaConstructible(
  386. const T* p, std::true_type /*has_get_arena*/) {
  387. return p->GetArena();
  388. }
  389. static Arena* GetArenaForAllocationForNonMessageNonArenaConstructible(
  390. const T* /* p */, std::false_type /*has_get_arena*/) {
  391. return nullptr;
  392. }
  393. template <typename U>
  394. static char DestructorSkippable(const typename U::DestructorSkippable_*);
  395. template <typename U>
  396. static double DestructorSkippable(...);
  397. typedef std::integral_constant<
  398. bool, sizeof(DestructorSkippable<T>(static_cast<const T*>(0))) ==
  399. sizeof(char) ||
  400. std::is_trivially_destructible<T>::value>
  401. is_destructor_skippable;
  402. template <typename U>
  403. static char ArenaConstructable(
  404. const typename U::InternalArenaConstructable_*);
  405. template <typename U>
  406. static double ArenaConstructable(...);
  407. typedef std::integral_constant<bool, sizeof(ArenaConstructable<T>(
  408. static_cast<const T*>(0))) ==
  409. sizeof(char)>
  410. is_arena_constructable;
  411. template <typename U,
  412. typename std::enable_if<
  413. std::is_same<Arena*, decltype(std::declval<const U>()
  414. .GetArena())>::value,
  415. int>::type = 0>
  416. static char HasGetArena(decltype(&U::GetArena));
  417. template <typename U>
  418. static double HasGetArena(...);
  419. typedef std::integral_constant<bool, sizeof(HasGetArena<T>(nullptr)) ==
  420. sizeof(char)>
  421. has_get_arena;
  422. template <typename... Args>
  423. static T* Construct(void* ptr, Args&&... args) {
  424. return new (ptr) T(static_cast<Args&&>(args)...);
  425. }
  426. static inline PROTOBUF_ALWAYS_INLINE T* New() {
  427. return new T(nullptr);
  428. }
  429. static Arena* GetArena(const T* p) { return p->GetArena(); }
  430. friend class Arena;
  431. friend class TestUtil::ReflectionTester;
  432. };
  433. // Provides access to protected GetOwningArena to generated messages. For
  434. // internal use only.
  435. template <typename T>
  436. static Arena* InternalGetOwningArena(const T* p) {
  437. return InternalHelper<T>::GetOwningArena(p);
  438. }
  439. // Provides access to protected GetArenaForAllocation to generated messages.
  440. // For internal use only.
  441. template <typename T>
  442. static Arena* InternalGetArenaForAllocation(const T* p) {
  443. return InternalHelper<T>::GetArenaForAllocationInternal(
  444. p, std::is_convertible<T*, MessageLite*>());
  445. }
  446. // Creates message-owned arena. For internal use only.
  447. static Arena* InternalCreateMessageOwnedArena() {
  448. return new Arena(internal::MessageOwned{});
  449. }
  450. // Checks whether this arena is message-owned. For internal use only.
  451. bool InternalIsMessageOwnedArena() { return IsMessageOwned(); }
  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>
  465. struct is_arena_constructable : InternalHelper<T>::is_arena_constructable {};
  466. template <typename T>
  467. struct is_destructor_skippable : InternalHelper<T>::is_destructor_skippable {
  468. };
  469. private:
  470. internal::ThreadSafeArena impl_;
  471. template <typename T>
  472. struct has_get_arena : InternalHelper<T>::has_get_arena {};
  473. // Constructor solely used by message-owned arena.
  474. inline Arena(internal::MessageOwned) : impl_(internal::MessageOwned{}) {}
  475. // Checks whether this arena is message-owned.
  476. PROTOBUF_ALWAYS_INLINE bool IsMessageOwned() const {
  477. return impl_.IsMessageOwned();
  478. }
  479. void ReturnArrayMemory(void* p, size_t size) {
  480. impl_.ReturnArrayMemory(p, size);
  481. }
  482. template <typename T, typename... Args>
  483. PROTOBUF_NDEBUG_INLINE static T* CreateMessageInternal(Arena* arena,
  484. Args&&... args) {
  485. static_assert(
  486. InternalHelper<T>::is_arena_constructable::value,
  487. "CreateMessage can only construct types that are ArenaConstructable");
  488. if (arena == NULL) {
  489. return new T(nullptr, static_cast<Args&&>(args)...);
  490. } else {
  491. return arena->DoCreateMessage<T>(static_cast<Args&&>(args)...);
  492. }
  493. }
  494. // This specialization for no arguments is necessary, because its behavior is
  495. // slightly different. When the arena pointer is nullptr, it calls T()
  496. // instead of T(nullptr).
  497. template <typename T>
  498. PROTOBUF_NDEBUG_INLINE static T* CreateMessageInternal(Arena* arena) {
  499. static_assert(
  500. InternalHelper<T>::is_arena_constructable::value,
  501. "CreateMessage can only construct types that are ArenaConstructable");
  502. if (arena == NULL) {
  503. // Generated arena constructor T(Arena*) is protected. Call via
  504. // InternalHelper.
  505. return InternalHelper<T>::New();
  506. } else {
  507. return arena->DoCreateMessage<T>();
  508. }
  509. }
  510. // Allocate and also optionally call collector with the allocated type info
  511. // when allocation recording is enabled.
  512. PROTOBUF_NDEBUG_INLINE void* AllocateInternal(size_t size, size_t align,
  513. void (*destructor)(void*),
  514. const std::type_info* type) {
  515. // Monitor allocation if needed.
  516. if (destructor == nullptr) {
  517. return AllocateAlignedWithHook(size, align, type);
  518. } else {
  519. if (align <= 8) {
  520. auto res = AllocateAlignedWithCleanup(internal::AlignUpTo8(size), type);
  521. res.second->elem = res.first;
  522. res.second->cleanup = destructor;
  523. return res.first;
  524. } else {
  525. auto res = AllocateAlignedWithCleanup(size + align - 8, type);
  526. auto ptr = internal::AlignTo(res.first, align);
  527. res.second->elem = ptr;
  528. res.second->cleanup = destructor;
  529. return ptr;
  530. }
  531. }
  532. }
  533. // CreateMessage<T> requires that T supports arenas, but this private method
  534. // works whether or not T supports arenas. These are not exposed to user code
  535. // as it can cause confusing API usages, and end up having double free in
  536. // user code. These are used only internally from LazyField and Repeated
  537. // fields, since they are designed to work in all mode combinations.
  538. template <typename Msg, typename... Args>
  539. PROTOBUF_ALWAYS_INLINE static Msg* DoCreateMaybeMessage(Arena* arena,
  540. std::true_type,
  541. Args&&... args) {
  542. return CreateMessageInternal<Msg>(arena, std::forward<Args>(args)...);
  543. }
  544. template <typename T, typename... Args>
  545. PROTOBUF_ALWAYS_INLINE static T* DoCreateMaybeMessage(Arena* arena,
  546. std::false_type,
  547. Args&&... args) {
  548. return Create<T>(arena, std::forward<Args>(args)...);
  549. }
  550. template <typename T, typename... Args>
  551. PROTOBUF_ALWAYS_INLINE static T* CreateMaybeMessage(Arena* arena,
  552. Args&&... args) {
  553. return DoCreateMaybeMessage<T>(arena, is_arena_constructable<T>(),
  554. std::forward<Args>(args)...);
  555. }
  556. // Just allocate the required size for the given type assuming the
  557. // type has a trivial constructor.
  558. template <typename T>
  559. PROTOBUF_NDEBUG_INLINE T* CreateInternalRawArray(size_t num_elements) {
  560. GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
  561. << "Requested size is too large to fit into size_t.";
  562. // We count on compiler to realize that if sizeof(T) is a multiple of
  563. // 8 AlignUpTo can be elided.
  564. const size_t n = sizeof(T) * num_elements;
  565. return static_cast<T*>(
  566. AllocateAlignedWithHookForArray(n, alignof(T), RTTI_TYPE_ID(T)));
  567. }
  568. template <typename T, typename... Args>
  569. PROTOBUF_NDEBUG_INLINE T* DoCreateMessage(Args&&... args) {
  570. return InternalHelper<T>::Construct(
  571. AllocateInternal(sizeof(T), alignof(T),
  572. internal::ObjectDestructor<
  573. InternalHelper<T>::is_destructor_skippable::value,
  574. T>::destructor,
  575. RTTI_TYPE_ID(T)),
  576. this, std::forward<Args>(args)...);
  577. }
  578. // CreateInArenaStorage is used to implement map field. Without it,
  579. // Map need to call generated message's protected arena constructor,
  580. // which needs to declare Map as friend of generated message.
  581. template <typename T, typename... Args>
  582. static void CreateInArenaStorage(T* ptr, Arena* arena, Args&&... args) {
  583. CreateInArenaStorageInternal(ptr, arena,
  584. typename is_arena_constructable<T>::type(),
  585. std::forward<Args>(args)...);
  586. if (arena != nullptr) {
  587. RegisterDestructorInternal(
  588. ptr, arena,
  589. typename InternalHelper<T>::is_destructor_skippable::type());
  590. }
  591. }
  592. template <typename T, typename... Args>
  593. static void CreateInArenaStorageInternal(T* ptr, Arena* arena,
  594. std::true_type, Args&&... args) {
  595. InternalHelper<T>::Construct(ptr, arena, std::forward<Args>(args)...);
  596. }
  597. template <typename T, typename... Args>
  598. static void CreateInArenaStorageInternal(T* ptr, Arena* /* arena */,
  599. std::false_type, Args&&... args) {
  600. new (ptr) T(std::forward<Args>(args)...);
  601. }
  602. template <typename T>
  603. static void RegisterDestructorInternal(T* /* ptr */, Arena* /* arena */,
  604. std::true_type) {}
  605. template <typename T>
  606. static void RegisterDestructorInternal(T* ptr, Arena* arena,
  607. std::false_type) {
  608. arena->OwnDestructor(ptr);
  609. }
  610. // These implement Create(). The second parameter has type 'true_type' if T is
  611. // a subtype of Message and 'false_type' otherwise.
  612. template <typename T, typename... Args>
  613. PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::true_type,
  614. Args&&... args) {
  615. if (arena == nullptr) {
  616. return new T(std::forward<Args>(args)...);
  617. } else {
  618. auto destructor =
  619. internal::ObjectDestructor<std::is_trivially_destructible<T>::value,
  620. T>::destructor;
  621. T* result =
  622. new (arena->AllocateInternal(sizeof(T), alignof(T), destructor,
  623. RTTI_TYPE_ID(T)))
  624. T(std::forward<Args>(args)...);
  625. return result;
  626. }
  627. }
  628. template <typename T, typename... Args>
  629. PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::false_type,
  630. Args&&... args) {
  631. if (arena == nullptr) {
  632. return new T(std::forward<Args>(args)...);
  633. } else {
  634. auto destructor =
  635. internal::ObjectDestructor<std::is_trivially_destructible<T>::value,
  636. T>::destructor;
  637. return new (arena->AllocateInternal(sizeof(T), alignof(T), destructor,
  638. RTTI_TYPE_ID(T)))
  639. T(std::forward<Args>(args)...);
  640. }
  641. }
  642. // These implement Own(), which registers an object for deletion (destructor
  643. // call and operator delete()). The second parameter has type 'true_type' if T
  644. // is a subtype of Message and 'false_type' otherwise. Collapsing
  645. // all template instantiations to one for generic Message reduces code size,
  646. // using the virtual destructor instead.
  647. template <typename T>
  648. PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::true_type) {
  649. if (object != NULL) {
  650. impl_.AddCleanup(object, &internal::arena_delete_object<MessageLite>);
  651. }
  652. }
  653. template <typename T>
  654. PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::false_type) {
  655. if (object != NULL) {
  656. impl_.AddCleanup(object, &internal::arena_delete_object<T>);
  657. }
  658. }
  659. // Implementation for GetArena(). Only message objects with
  660. // InternalArenaConstructable_ tags can be associated with an arena, and such
  661. // objects must implement a GetArena() method.
  662. template <typename T, typename std::enable_if<
  663. is_arena_constructable<T>::value, int>::type = 0>
  664. PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
  665. return InternalHelper<T>::GetArena(value);
  666. }
  667. template <typename T,
  668. typename std::enable_if<!is_arena_constructable<T>::value &&
  669. has_get_arena<T>::value,
  670. int>::type = 0>
  671. PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
  672. return value->GetArena();
  673. }
  674. template <typename T,
  675. typename std::enable_if<!is_arena_constructable<T>::value &&
  676. !has_get_arena<T>::value,
  677. int>::type = 0>
  678. PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
  679. (void)value;
  680. return nullptr;
  681. }
  682. template <typename T>
  683. PROTOBUF_ALWAYS_INLINE static Arena* GetOwningArena(const T* value) {
  684. return GetOwningArenaInternal(
  685. value, std::is_convertible<T*, MessageLite*>());
  686. }
  687. // Implementation for GetOwningArena(). All and only message objects have
  688. // GetOwningArena() method.
  689. template <typename T>
  690. PROTOBUF_ALWAYS_INLINE static Arena* GetOwningArenaInternal(
  691. const T* value, std::true_type) {
  692. return InternalHelper<T>::GetOwningArena(value);
  693. }
  694. template <typename T>
  695. PROTOBUF_ALWAYS_INLINE static Arena* GetOwningArenaInternal(
  696. const T* /* value */, std::false_type) {
  697. return nullptr;
  698. }
  699. void* AllocateAlignedWithHookForArray(size_t n, size_t align,
  700. const std::type_info* type) {
  701. if (align <= 8) {
  702. return AllocateAlignedWithHookForArray(internal::AlignUpTo8(n), type);
  703. } else {
  704. // We are wasting space by over allocating align - 8 bytes. Compared
  705. // to a dedicated function that takes current alignment in consideration.
  706. // Such a scheme would only waste (align - 8)/2 bytes on average, but
  707. // requires a dedicated function in the outline arena allocation
  708. // functions. Possibly re-evaluate tradeoffs later.
  709. return internal::AlignTo(
  710. AllocateAlignedWithHookForArray(n + align - 8, type), align);
  711. }
  712. }
  713. void* AllocateAlignedWithHook(size_t n, size_t align,
  714. const std::type_info* type) {
  715. if (align <= 8) {
  716. return AllocateAlignedWithHook(internal::AlignUpTo8(n), type);
  717. } else {
  718. // We are wasting space by over allocating align - 8 bytes. Compared
  719. // to a dedicated function that takes current alignment in consideration.
  720. // Such a scheme would only waste (align - 8)/2 bytes on average, but
  721. // requires a dedicated function in the outline arena allocation
  722. // functions. Possibly re-evaluate tradeoffs later.
  723. return internal::AlignTo(AllocateAlignedWithHook(n + align - 8, type),
  724. align);
  725. }
  726. }
  727. void* AllocateAlignedNoHook(size_t n);
  728. void* AllocateAlignedWithHook(size_t n, const std::type_info* type);
  729. void* AllocateAlignedWithHookForArray(size_t n, const std::type_info* type);
  730. std::pair<void*, internal::SerialArena::CleanupNode*>
  731. AllocateAlignedWithCleanup(size_t n, const std::type_info* type);
  732. template <typename Type>
  733. friend class internal::GenericTypeHandler;
  734. friend class internal::InternalMetadata; // For user_arena().
  735. friend class internal::LazyField; // For CreateMaybeMessage.
  736. friend class internal::EpsCopyInputStream; // For parser performance
  737. friend class MessageLite;
  738. template <typename Key, typename T>
  739. friend class Map;
  740. template <typename>
  741. friend class RepeatedField; // For ReturnArrayMemory
  742. friend class internal::RepeatedPtrFieldBase; // For ReturnArrayMemory
  743. friend struct internal::ArenaTestPeer;
  744. };
  745. // Defined above for supporting environments without RTTI.
  746. #undef RTTI_TYPE_ID
  747. } // namespace protobuf
  748. } // namespace google
  749. #include <google/protobuf/port_undef.inc>
  750. #endif // GOOGLE_PROTOBUF_ARENA_H__