诸暨麻将添加redis
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

725 line
30 KiB

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