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 43 kB

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