arena.h 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915
  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. #ifndef GOOGLE_PROTOBUF_ARENA_H__
  31. #define GOOGLE_PROTOBUF_ARENA_H__
  32. #include <limits>
  33. #ifdef max
  34. #undef max // Visual Studio defines this macro
  35. #endif
  36. #if __cplusplus >= 201103L
  37. #include <google/protobuf/stubs/type_traits.h>
  38. #endif
  39. #include <typeinfo>
  40. #include <google/protobuf/stubs/atomic_sequence_num.h>
  41. #include <google/protobuf/stubs/atomicops.h>
  42. #include <google/protobuf/stubs/common.h>
  43. #include <google/protobuf/stubs/logging.h>
  44. #include <google/protobuf/stubs/mutex.h>
  45. #include <google/protobuf/stubs/type_traits.h>
  46. namespace google {
  47. namespace protobuf {
  48. class Arena; // defined below
  49. class Message; // message.h
  50. namespace internal {
  51. class ArenaString; // arenastring.h
  52. class LazyField; // lazy_field.h
  53. template<typename Type>
  54. class GenericTypeHandler; // repeated_field.h
  55. // Templated cleanup methods.
  56. template<typename T> void arena_destruct_object(void* object) {
  57. reinterpret_cast<T*>(object)->~T();
  58. }
  59. template<typename T> void arena_delete_object(void* object) {
  60. delete reinterpret_cast<T*>(object);
  61. }
  62. inline void arena_free(void* object, size_t size) {
  63. free(object);
  64. }
  65. } // namespace internal
  66. // ArenaOptions provides optional additional parameters to arena construction
  67. // that control its block-allocation behavior.
  68. struct ArenaOptions {
  69. // This defines the size of the first block requested from the system malloc.
  70. // Subsequent block sizes will increase in a geometric series up to a maximum.
  71. size_t start_block_size;
  72. // This defines the maximum block size requested from system malloc (unless an
  73. // individual arena allocation request occurs with a size larger than this
  74. // maximum). Requested block sizes increase up to this value, then remain
  75. // here.
  76. size_t max_block_size;
  77. // An initial block of memory for the arena to use, or NULL for none. If
  78. // provided, the block must live at least as long as the arena itself. The
  79. // creator of the Arena retains ownership of the block after the Arena is
  80. // destroyed.
  81. char* initial_block;
  82. // The size of the initial block, if provided.
  83. size_t initial_block_size;
  84. // A function pointer to an alloc method that returns memory blocks of size
  85. // requested. By default, it contains a ptr to the malloc function.
  86. //
  87. // NOTE: block_alloc and dealloc functions are expected to behave like
  88. // malloc and free, including Asan poisoning.
  89. void* (*block_alloc)(size_t);
  90. // A function pointer to a dealloc method that takes ownership of the blocks
  91. // from the arena. By default, it contains a ptr to a wrapper function that
  92. // calls free.
  93. void (*block_dealloc)(void*, size_t);
  94. // Hooks for adding external functionality such as user-specific metrics
  95. // collection, specific debugging abilities, etc.
  96. // Init hook may return a pointer to a cookie to be stored in the arena.
  97. // reset and destruction hooks will then be called with the same cookie
  98. // pointer. This allows us to save an external object per arena instance and
  99. // use it on the other hooks (Note: It is just as legal for init to return
  100. // NULL and not use the cookie feature).
  101. // on_arena_reset and on_arena_destruction also receive the space used in
  102. // the arena just before the reset.
  103. void* (*on_arena_init)(Arena* arena);
  104. void (*on_arena_reset)(Arena* arena, void* cookie, uint64 space_used);
  105. void (*on_arena_destruction)(Arena* arena, void* cookie, uint64 space_used);
  106. // type_info is promised to be static - its lifetime extends to
  107. // match program's lifetime (It is given by typeid operator).
  108. // Note: typeid(void) will be passed as allocated_type every time we
  109. // intentionally want to avoid monitoring an allocation. (i.e. internal
  110. // allocations for managing the arena)
  111. void (*on_arena_allocation)(const std::type_info* allocated_type,
  112. uint64 alloc_size, void* cookie);
  113. ArenaOptions()
  114. : start_block_size(kDefaultStartBlockSize),
  115. max_block_size(kDefaultMaxBlockSize),
  116. initial_block(NULL),
  117. initial_block_size(0),
  118. block_alloc(&malloc),
  119. block_dealloc(&internal::arena_free),
  120. on_arena_init(NULL),
  121. on_arena_reset(NULL),
  122. on_arena_destruction(NULL),
  123. on_arena_allocation(NULL) {}
  124. private:
  125. // Constants define default starting block size and max block size for
  126. // arena allocator behavior -- see descriptions above.
  127. static const size_t kDefaultStartBlockSize = 256;
  128. static const size_t kDefaultMaxBlockSize = 8192;
  129. };
  130. // Support for non-RTTI environments. (The metrics hooks API uses type
  131. // information.)
  132. #ifndef GOOGLE_PROTOBUF_NO_RTTI
  133. #define RTTI_TYPE_ID(type) (&typeid(type))
  134. #else
  135. #define RTTI_TYPE_ID(type) (NULL)
  136. #endif
  137. // Arena allocator. Arena allocation replaces ordinary (heap-based) allocation
  138. // with new/delete, and improves performance by aggregating allocations into
  139. // larger blocks and freeing allocations all at once. Protocol messages are
  140. // allocated on an arena by using Arena::CreateMessage<T>(Arena*), below, and
  141. // are automatically freed when the arena is destroyed.
  142. //
  143. // This is a thread-safe implementation: multiple threads may allocate from the
  144. // arena concurrently. Destruction is not thread-safe and the destructing
  145. // thread must synchronize with users of the arena first.
  146. //
  147. // An arena provides two allocation interfaces: CreateMessage<T>, which works
  148. // for arena-enabled proto2 message types as well as other types that satisfy
  149. // the appropriate protocol (described below), and Create<T>, which works for
  150. // any arbitrary type T. CreateMessage<T> is better when the type T supports it,
  151. // because this interface (i) passes the arena pointer to the created object so
  152. // that its sub-objects and internal allocations can use the arena too, and (ii)
  153. // elides the object's destructor call when possible. Create<T> does not place
  154. // any special requirements on the type T, and will invoke the object's
  155. // destructor when the arena is destroyed.
  156. //
  157. // The arena message allocation protocol, required by CreateMessage<T>, is as
  158. // follows:
  159. //
  160. // - The type T must have (at least) two constructors: a constructor with no
  161. // arguments, called when a T is allocated on the heap; and a constructor with
  162. // a google::protobuf::Arena* argument, called when a T is allocated on an arena. If the
  163. // second constructor is called with a NULL arena pointer, it must be
  164. // equivalent to invoking the first (no-argument) constructor.
  165. //
  166. // - The type T must have a particular type trait: a nested type
  167. // |InternalArenaConstructable_|. This is usually a typedef to |void|. If no
  168. // such type trait exists, then the instantiation CreateMessage<T> will fail
  169. // to compile.
  170. //
  171. // - The type T *may* have the type trait |DestructorSkippable_|. If this type
  172. // trait is present in the type, then its destructor will not be called if and
  173. // only if it was passed a non-NULL arena pointer. If this type trait is not
  174. // present on the type, then its destructor is always called when the
  175. // containing arena is destroyed.
  176. //
  177. // - One- and two-user-argument forms of CreateMessage<T>() also exist that
  178. // forward these constructor arguments to T's constructor: for example,
  179. // CreateMessage<T>(Arena*, arg1, arg2) forwards to a constructor T(Arena*,
  180. // arg1, arg2).
  181. //
  182. // This protocol is implemented by all arena-enabled proto2 message classes as
  183. // well as RepeatedPtrField.
  184. class LIBPROTOBUF_EXPORT Arena {
  185. public:
  186. // Arena constructor taking custom options. See ArenaOptions below for
  187. // descriptions of the options available.
  188. explicit Arena(const ArenaOptions& options) : options_(options) {
  189. Init();
  190. }
  191. // Default constructor with sensible default options, tuned for average
  192. // use-cases.
  193. Arena() {
  194. Init();
  195. }
  196. // Destructor deletes all owned heap allocated objects, and destructs objects
  197. // that have non-trivial destructors, except for proto2 message objects whose
  198. // destructors can be skipped. Also, frees all blocks except the initial block
  199. // if it was passed in.
  200. ~Arena();
  201. // API to create proto2 message objects on the arena. If the arena passed in
  202. // is NULL, then a heap allocated object is returned. Type T must be a message
  203. // defined in a .proto file with cc_enable_arenas set to true, otherwise a
  204. // compilation error will occur.
  205. //
  206. // RepeatedField and RepeatedPtrField may also be instantiated directly on an
  207. // arena with this method.
  208. //
  209. // This function also accepts any type T that satisfies the arena message
  210. // allocation protocol, documented above.
  211. template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  212. static T* CreateMessage(::google::protobuf::Arena* arena) {
  213. if (arena == NULL) {
  214. return new T;
  215. } else {
  216. return arena->CreateMessageInternal<T>(static_cast<T*>(0));
  217. }
  218. }
  219. // One-argument form of CreateMessage. This is useful for constructing objects
  220. // that implement the arena message construction protocol described above but
  221. // take additional constructor arguments.
  222. template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  223. static T* CreateMessage(::google::protobuf::Arena* arena, const Arg& arg) {
  224. if (arena == NULL) {
  225. return new T(NULL, arg);
  226. } else {
  227. return arena->CreateMessageInternal<T>(static_cast<T*>(0),
  228. arg);
  229. }
  230. }
  231. // Two-argument form of CreateMessage. This is useful for constructing objects
  232. // that implement the arena message construction protocol described above but
  233. // take additional constructor arguments.
  234. template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  235. static T* CreateMessage(::google::protobuf::Arena* arena,
  236. const Arg1& arg1,
  237. const Arg2& arg2) {
  238. if (arena == NULL) {
  239. return new T(NULL, arg1, arg2);
  240. } else {
  241. return arena->CreateMessageInternal<T>(static_cast<T*>(0),
  242. arg1, arg2);
  243. }
  244. }
  245. // API to create any objects on the arena. Note that only the object will
  246. // be created on the arena; the underlying ptrs (in case of a proto2 message)
  247. // will be still heap allocated. Proto messages should usually be allocated
  248. // with CreateMessage<T>() instead.
  249. //
  250. // Note that even if T satisfies the arena message construction protocol
  251. // (InternalArenaConstructable_ trait and optional DestructorSkippable_
  252. // trait), as described above, this function does not follow the protocol;
  253. // instead, it treats T as a black-box type, just as if it did not have these
  254. // traits. Specifically, T's constructor arguments will always be only those
  255. // passed to Create<T>() -- no additional arena pointer is implicitly added.
  256. // Furthermore, the destructor will always be called at arena destruction time
  257. // (unless the destructor is trivial). Hence, from T's point of view, it is as
  258. // if the object were allocated on the heap (except that the underlying memory
  259. // is obtained from the arena).
  260. template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  261. static T* Create(::google::protobuf::Arena* arena) {
  262. if (arena == NULL) {
  263. return new T();
  264. } else {
  265. return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value);
  266. }
  267. }
  268. // Version of the above with one constructor argument for the created object.
  269. template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  270. static T* Create(::google::protobuf::Arena* arena, const Arg& arg) {
  271. if (arena == NULL) {
  272. return new T(arg);
  273. } else {
  274. return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
  275. arg);
  276. }
  277. }
  278. // Version of the above with two constructor arguments for the created object.
  279. template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  280. static T* Create(::google::protobuf::Arena* arena, const Arg1& arg1, const Arg2& arg2) {
  281. if (arena == NULL) {
  282. return new T(arg1, arg2);
  283. } else {
  284. return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
  285. arg1, arg2);
  286. }
  287. }
  288. // Version of the above with three constructor arguments for the created
  289. // object.
  290. template <typename T, typename Arg1, typename Arg2, typename Arg3>
  291. GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
  292. const Arg1& arg1, const Arg2& arg2,
  293. const Arg3& arg3) {
  294. if (arena == NULL) {
  295. return new T(arg1, arg2, arg3);
  296. } else {
  297. return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
  298. arg1, arg2, arg3);
  299. }
  300. }
  301. // Version of the above with four constructor arguments for the created
  302. // object.
  303. template <typename T, typename Arg1, typename Arg2, typename Arg3,
  304. typename Arg4>
  305. GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
  306. const Arg1& arg1, const Arg2& arg2,
  307. const Arg3& arg3, const Arg4& arg4) {
  308. if (arena == NULL) {
  309. return new T(arg1, arg2, arg3, arg4);
  310. } else {
  311. return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
  312. arg1, arg2, arg3, arg4);
  313. }
  314. }
  315. // Version of the above with five constructor arguments for the created
  316. // object.
  317. template <typename T, typename Arg1, typename Arg2, typename Arg3,
  318. typename Arg4, typename Arg5>
  319. GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
  320. const Arg1& arg1, const Arg2& arg2,
  321. const Arg3& arg3, const Arg4& arg4,
  322. const Arg5& arg5) {
  323. if (arena == NULL) {
  324. return new T(arg1, arg2, arg3, arg4, arg5);
  325. } else {
  326. return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
  327. arg1, arg2, arg3, arg4, arg5);
  328. }
  329. }
  330. // Version of the above with six constructor arguments for the created
  331. // object.
  332. template <typename T, typename Arg1, typename Arg2, typename Arg3,
  333. typename Arg4, typename Arg5, typename Arg6>
  334. GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
  335. const Arg1& arg1, const Arg2& arg2,
  336. const Arg3& arg3, const Arg4& arg4,
  337. const Arg5& arg5, const Arg6& arg6) {
  338. if (arena == NULL) {
  339. return new T(arg1, arg2, arg3, arg4, arg5, arg6);
  340. } else {
  341. return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
  342. arg1, arg2, arg3, arg4, arg5, arg6);
  343. }
  344. }
  345. // Version of the above with seven constructor arguments for the created
  346. // object.
  347. template <typename T, typename Arg1, typename Arg2, typename Arg3,
  348. typename Arg4, typename Arg5, typename Arg6, typename Arg7>
  349. GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
  350. const Arg1& arg1, const Arg2& arg2,
  351. const Arg3& arg3, const Arg4& arg4,
  352. const Arg5& arg5, const Arg6& arg6,
  353. const Arg7& arg7) {
  354. if (arena == NULL) {
  355. return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  356. } else {
  357. return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
  358. arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  359. }
  360. }
  361. // Version of the above with eight constructor arguments for the created
  362. // object.
  363. template <typename T, typename Arg1, typename Arg2, typename Arg3,
  364. typename Arg4, typename Arg5, typename Arg6, typename Arg7,
  365. typename Arg8>
  366. GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
  367. const Arg1& arg1, const Arg2& arg2,
  368. const Arg3& arg3, const Arg4& arg4,
  369. const Arg5& arg5, const Arg6& arg6,
  370. const Arg7& arg7, const Arg8& arg8) {
  371. if (arena == NULL) {
  372. return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
  373. } else {
  374. return arena->CreateInternal<T>(
  375. google::protobuf::internal::has_trivial_destructor<T>::value,
  376. arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
  377. }
  378. }
  379. // Create an array of object type T on the arena *without* invoking the
  380. // constructor of T. If `arena` is null, then the return value should be freed
  381. // with `delete[] x;` (or `::operator delete[](x);`).
  382. // To ensure safe uses, this function checks at compile time
  383. // (when compiled as C++11) that T is trivially default-constructible and
  384. // trivially destructible.
  385. template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  386. static T* CreateArray(::google::protobuf::Arena* arena, size_t num_elements) {
  387. GOOGLE_CHECK_LE(num_elements,
  388. std::numeric_limits<size_t>::max() / sizeof(T))
  389. << "Requested size is too large to fit into size_t.";
  390. if (arena == NULL) {
  391. return static_cast<T*>(::operator new[](num_elements * sizeof(T)));
  392. } else {
  393. return arena->CreateInternalRawArray<T>(num_elements);
  394. }
  395. }
  396. // Returns the total space used by the arena, which is the sums of the sizes
  397. // of the underlying blocks. The total space used may not include the new
  398. // blocks that are allocated by this arena from other threads concurrently
  399. // with the call to this method.
  400. GOOGLE_ATTRIBUTE_NOINLINE uint64 SpaceAllocated() const;
  401. // As above, but does not include any free space in underlying blocks.
  402. GOOGLE_ATTRIBUTE_NOINLINE uint64 SpaceUsed() const;
  403. // Frees all storage allocated by this arena after calling destructors
  404. // registered with OwnDestructor() and freeing objects registered with Own().
  405. // Any objects allocated on this arena are unusable after this call. It also
  406. // returns the total space used by the arena which is the sums of the sizes
  407. // of the allocated blocks. This method is not thread-safe.
  408. GOOGLE_ATTRIBUTE_NOINLINE uint64 Reset();
  409. // Adds |object| to a list of heap-allocated objects to be freed with |delete|
  410. // when the arena is destroyed or reset.
  411. template <typename T> GOOGLE_ATTRIBUTE_NOINLINE
  412. void Own(T* object) {
  413. OwnInternal(object, google::protobuf::internal::is_convertible<T*, ::google::protobuf::Message*>());
  414. }
  415. // Adds |object| to a list of objects whose destructors will be manually
  416. // called when the arena is destroyed or reset. This differs from Own() in
  417. // that it does not free the underlying memory with |delete|; hence, it is
  418. // normally only used for objects that are placement-newed into
  419. // arena-allocated memory.
  420. template <typename T> GOOGLE_ATTRIBUTE_NOINLINE
  421. void OwnDestructor(T* object) {
  422. if (object != NULL) {
  423. AddListNode(object, &internal::arena_destruct_object<T>);
  424. }
  425. }
  426. // Adds a custom member function on an object to the list of destructors that
  427. // will be manually called when the arena is destroyed or reset. This differs
  428. // from OwnDestructor() in that any member function may be specified, not only
  429. // the class destructor.
  430. GOOGLE_ATTRIBUTE_NOINLINE void OwnCustomDestructor(void* object,
  431. void (*destruct)(void*)) {
  432. AddListNode(object, destruct);
  433. }
  434. // Retrieves the arena associated with |value| if |value| is an arena-capable
  435. // message, or NULL otherwise. This differs from value->GetArena() in that the
  436. // latter is a virtual call, while this method is a templated call that
  437. // resolves at compile-time.
  438. template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  439. static ::google::protobuf::Arena* GetArena(const T* value) {
  440. return GetArenaInternal(value, static_cast<T*>(0));
  441. }
  442. // Helper typetrait that indicates support for arenas in a type T at compile
  443. // time. This is public only to allow construction of higher-level templated
  444. // utilities. is_arena_constructable<T>::value is an instance of
  445. // google::protobuf::internal::true_type if the message type T has arena support enabled, and
  446. // google::protobuf::internal::false_type otherwise.
  447. //
  448. // This is inside Arena because only Arena has the friend relationships
  449. // necessary to see the underlying generated code traits.
  450. template<typename T>
  451. struct is_arena_constructable {
  452. template<typename U>
  453. static char ArenaConstructable(
  454. const typename U::InternalArenaConstructable_*);
  455. template<typename U>
  456. static double ArenaConstructable(...);
  457. // This will resolve to either google::protobuf::internal::true_type or google::protobuf::internal::false_type.
  458. typedef google::protobuf::internal::integral_constant<bool,
  459. sizeof(ArenaConstructable<const T>(static_cast<const T*>(0))) ==
  460. sizeof(char)> type;
  461. static const type value;
  462. };
  463. private:
  464. // Blocks are variable length malloc-ed objects. The following structure
  465. // describes the common header for all blocks.
  466. struct Block {
  467. void* owner; // &ThreadCache of thread that owns this block, or
  468. // &this->owner if not yet owned by a thread.
  469. Block* next; // Next block in arena (may have different owner)
  470. // ((char*) &block) + pos is next available byte. It is always
  471. // aligned at a multiple of 8 bytes.
  472. size_t pos;
  473. size_t size; // total size of the block.
  474. GOOGLE_ATTRIBUTE_ALWAYS_INLINE size_t avail() const { return size - pos; }
  475. // data follows
  476. };
  477. template<typename Type> friend class ::google::protobuf::internal::GenericTypeHandler;
  478. friend class MockArena; // For unit-testing.
  479. friend class internal::ArenaString; // For AllocateAligned.
  480. friend class internal::LazyField; // For CreateMaybeMessage.
  481. struct ThreadCache {
  482. // The ThreadCache is considered valid as long as this matches the
  483. // lifecycle_id of the arena being used.
  484. int64 last_lifecycle_id_seen;
  485. Block* last_block_used_;
  486. };
  487. static const size_t kHeaderSize = sizeof(Block);
  488. static google::protobuf::internal::SequenceNumber lifecycle_id_generator_;
  489. #ifdef PROTOBUF_USE_DLLS
  490. // Thread local variables cannot be exposed through DLL interface but we can
  491. // wrap them in static functions.
  492. static ThreadCache& thread_cache();
  493. #elif defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
  494. // Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread
  495. // local storage class we implemented.
  496. // iOS also does not support the GOOGLE_THREAD_LOCAL keyword.
  497. static ThreadCache& thread_cache();
  498. #else
  499. static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
  500. static ThreadCache& thread_cache() { return thread_cache_; }
  501. #endif
  502. // SFINAE for skipping addition to delete list for a message type when created
  503. // with CreateMessage. This is mainly to skip proto2/proto1 message objects
  504. // with cc_enable_arenas=true from being part of the delete list. Also, note,
  505. // compiler will optimize out the branch in CreateInternal<T>.
  506. template<typename T>
  507. static inline bool SkipDeleteList(typename T::DestructorSkippable_*) {
  508. return true;
  509. }
  510. // For message objects that don't have the DestructorSkippable_ trait, we
  511. // always add to the delete list.
  512. template<typename T>
  513. static inline bool SkipDeleteList(...) {
  514. return google::protobuf::internal::has_trivial_destructor<T>::value;
  515. }
  516. // Helper typetrait that indicates whether the desctructor of type T should be
  517. // called when arena is destroyed at compile time. This is only to allow
  518. // construction of higher-level templated utilities.
  519. // is_destructor_skippable<T>::value is an instance of google::protobuf::internal::true_type if the
  520. // destructor of the message type T should not be called when arena is
  521. // destroyed or google::protobuf::internal::has_trivial_destructor<T>::value == true, and
  522. // google::protobuf::internal::false_type otherwise.
  523. //
  524. // This is inside Arena because only Arena has the friend relationships
  525. // necessary to see the underlying generated code traits.
  526. template<typename T>
  527. struct is_destructor_skippable {
  528. template<typename U>
  529. static char DestructorSkippable(
  530. const typename U::DestructorSkippable_*);
  531. template<typename U>
  532. static double DestructorSkippable(...);
  533. // This will resolve to either google::protobuf::internal::true_type or google::protobuf::internal::false_type.
  534. typedef google::protobuf::internal::integral_constant<bool,
  535. sizeof(DestructorSkippable<const T>(static_cast<const T*>(0))) ==
  536. sizeof(char) || google::protobuf::internal::has_trivial_destructor<T>::value == true>
  537. type;
  538. static const type value;
  539. };
  540. // CreateMessage<T> requires that T supports arenas, but this private method
  541. // works whether or not T supports arenas. These are not exposed to user code
  542. // as it can cause confusing API usages, and end up having double free in
  543. // user code. These are used only internally from LazyField and Repeated
  544. // fields, since they are designed to work in all mode combinations.
  545. template<typename Msg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  546. static Msg* CreateMaybeMessage(
  547. Arena* arena, typename Msg::InternalArenaConstructable_*) {
  548. return CreateMessage<Msg>(arena);
  549. }
  550. template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  551. static T* CreateMaybeMessage(Arena* arena, ...) {
  552. return Create<T>(arena);
  553. }
  554. // Just allocate the required size for the given type assuming the
  555. // type has a trivial constructor.
  556. template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  557. T* CreateInternalRawArray(size_t num_elements) {
  558. GOOGLE_CHECK_LE(num_elements,
  559. std::numeric_limits<size_t>::max() / sizeof(T))
  560. << "Requested size is too large to fit into size_t.";
  561. return static_cast<T*>(
  562. AllocateAligned(RTTI_TYPE_ID(T), sizeof(T) * num_elements));
  563. }
  564. template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  565. T* CreateInternal(bool skip_explicit_ownership) {
  566. T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T();
  567. if (!skip_explicit_ownership) {
  568. AddListNode(t, &internal::arena_destruct_object<T>);
  569. }
  570. return t;
  571. }
  572. template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  573. T* CreateInternal(bool skip_explicit_ownership, const Arg& arg) {
  574. T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg);
  575. if (!skip_explicit_ownership) {
  576. AddListNode(t, &internal::arena_destruct_object<T>);
  577. }
  578. return t;
  579. }
  580. template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  581. T* CreateInternal(
  582. bool skip_explicit_ownership, const Arg1& arg1, const Arg2& arg2) {
  583. T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg1, arg2);
  584. if (!skip_explicit_ownership) {
  585. AddListNode(t, &internal::arena_destruct_object<T>);
  586. }
  587. return t;
  588. }
  589. template <typename T, typename Arg1, typename Arg2, typename Arg3>
  590. GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
  591. const Arg1& arg1,
  592. const Arg2& arg2,
  593. const Arg3& arg3) {
  594. T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
  595. T(arg1, arg2, arg3);
  596. if (!skip_explicit_ownership) {
  597. AddListNode(t, &internal::arena_destruct_object<T>);
  598. }
  599. return t;
  600. }
  601. template <typename T, typename Arg1, typename Arg2, typename Arg3,
  602. typename Arg4>
  603. GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
  604. const Arg1& arg1,
  605. const Arg2& arg2,
  606. const Arg3& arg3,
  607. const Arg4& arg4) {
  608. T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
  609. T(arg1, arg2, arg3, arg4);
  610. if (!skip_explicit_ownership) {
  611. AddListNode(t, &internal::arena_destruct_object<T>);
  612. }
  613. return t;
  614. }
  615. template <typename T, typename Arg1, typename Arg2, typename Arg3,
  616. typename Arg4, typename Arg5>
  617. GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
  618. const Arg1& arg1,
  619. const Arg2& arg2,
  620. const Arg3& arg3,
  621. const Arg4& arg4,
  622. const Arg5& arg5) {
  623. T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
  624. T(arg1, arg2, arg3, arg4, arg5);
  625. if (!skip_explicit_ownership) {
  626. AddListNode(t, &internal::arena_destruct_object<T>);
  627. }
  628. return t;
  629. }
  630. template <typename T, typename Arg1, typename Arg2, typename Arg3,
  631. typename Arg4, typename Arg5, typename Arg6>
  632. GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
  633. const Arg1& arg1,
  634. const Arg2& arg2,
  635. const Arg3& arg3,
  636. const Arg4& arg4,
  637. const Arg5& arg5,
  638. const Arg6& arg6) {
  639. T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
  640. T(arg1, arg2, arg3, arg4, arg5, arg6);
  641. if (!skip_explicit_ownership) {
  642. AddListNode(t, &internal::arena_destruct_object<T>);
  643. }
  644. return t;
  645. }
  646. template <typename T, typename Arg1, typename Arg2, typename Arg3,
  647. typename Arg4, typename Arg5, typename Arg6, typename Arg7>
  648. GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
  649. const Arg1& arg1,
  650. const Arg2& arg2,
  651. const Arg3& arg3,
  652. const Arg4& arg4,
  653. const Arg5& arg5,
  654. const Arg6& arg6,
  655. const Arg7& arg7) {
  656. T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
  657. T(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  658. if (!skip_explicit_ownership) {
  659. AddListNode(t, &internal::arena_destruct_object<T>);
  660. }
  661. return t;
  662. }
  663. template <typename T, typename Arg1, typename Arg2, typename Arg3,
  664. typename Arg4, typename Arg5, typename Arg6, typename Arg7,
  665. typename Arg8>
  666. GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
  667. const Arg1& arg1,
  668. const Arg2& arg2,
  669. const Arg3& arg3,
  670. const Arg4& arg4,
  671. const Arg5& arg5,
  672. const Arg6& arg6,
  673. const Arg7& arg7,
  674. const Arg8& arg8) {
  675. T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
  676. T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
  677. if (!skip_explicit_ownership) {
  678. AddListNode(t, &internal::arena_destruct_object<T>);
  679. }
  680. return t;
  681. }
  682. template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  683. T* CreateMessageInternal(typename T::InternalArenaConstructable_*) {
  684. return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
  685. this);
  686. }
  687. template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  688. T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
  689. const Arg& arg) {
  690. return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
  691. this, arg);
  692. }
  693. template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  694. T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
  695. const Arg1& arg1, const Arg2& arg2) {
  696. return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
  697. this, arg1, arg2);
  698. }
  699. // CreateInArenaStorage is used to implement map field. Without it,
  700. // google::protobuf::Map need to call generated message's protected arena constructor,
  701. // which needs to declare google::protobuf::Map as friend of generated message.
  702. template <typename T>
  703. static void CreateInArenaStorage(T* ptr, Arena* arena) {
  704. CreateInArenaStorageInternal(ptr, arena, is_arena_constructable<T>::value);
  705. RegisterDestructorInternal(ptr, arena, is_destructor_skippable<T>::value);
  706. }
  707. template <typename T>
  708. static void CreateInArenaStorageInternal(
  709. T* ptr, Arena* arena, google::protobuf::internal::true_type) {
  710. new (ptr) T(arena);
  711. }
  712. template <typename T>
  713. static void CreateInArenaStorageInternal(
  714. T* ptr, Arena* arena, google::protobuf::internal::false_type) {
  715. new (ptr) T;
  716. }
  717. template <typename T>
  718. static void RegisterDestructorInternal(
  719. T* ptr, Arena* arena, google::protobuf::internal::true_type) {}
  720. template <typename T>
  721. static void RegisterDestructorInternal(
  722. T* ptr, Arena* arena, google::protobuf::internal::false_type) {
  723. arena->OwnDestructor(ptr);
  724. }
  725. // These implement Own(), which registers an object for deletion (destructor
  726. // call and operator delete()). The second parameter has type 'true_type' if T
  727. // is a subtype of ::google::protobuf::Message and 'false_type' otherwise. Collapsing
  728. // all template instantiations to one for generic Message reduces code size,
  729. // using the virtual destructor instead.
  730. template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  731. void OwnInternal(T* object, google::protobuf::internal::true_type) {
  732. if (object != NULL) {
  733. AddListNode(object, &internal::arena_delete_object< ::google::protobuf::Message >);
  734. }
  735. }
  736. template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  737. void OwnInternal(T* object, google::protobuf::internal::false_type) {
  738. if (object != NULL) {
  739. AddListNode(object, &internal::arena_delete_object<T>);
  740. }
  741. }
  742. // Implementation for GetArena(). Only message objects with
  743. // InternalArenaConstructable_ tags can be associated with an arena, and such
  744. // objects must implement a GetArenaNoVirtual() method.
  745. template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  746. static ::google::protobuf::Arena* GetArenaInternal(
  747. const T* value, typename T::InternalArenaConstructable_*) {
  748. return value->GetArenaNoVirtual();
  749. }
  750. template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
  751. static ::google::protobuf::Arena* GetArenaInternal(const T* value, ...) {
  752. return NULL;
  753. }
  754. // Allocate and also optionally call on_arena_allocation callback with the
  755. // allocated type info when the hooks are in place in ArenaOptions and
  756. // the cookie is not null.
  757. void* AllocateAligned(const std::type_info* allocated, size_t n);
  758. // Allocate an internal allocation, avoiding optional typed monitoring.
  759. GOOGLE_ATTRIBUTE_ALWAYS_INLINE void* AllocateAligned(size_t n) {
  760. return AllocateAligned(NULL, n);
  761. }
  762. void Init();
  763. // Free all blocks and return the total space used which is the sums of sizes
  764. // of the all the allocated blocks.
  765. uint64 FreeBlocks();
  766. // Add object pointer and cleanup function pointer to the list.
  767. // TODO(rohananil, cfallin): We could pass in a sub-arena into this method
  768. // to avoid polluting blocks of this arena with list nodes. This would help in
  769. // mixed mode (where many protobufs have cc_enable_arenas=false), and is an
  770. // alternative to a chunked linked-list, but with extra overhead of *next.
  771. void AddListNode(void* elem, void (*cleanup)(void*));
  772. // Delete or Destruct all objects owned by the arena.
  773. void CleanupList();
  774. uint64 ResetInternal();
  775. inline void SetThreadCacheBlock(Block* block) {
  776. thread_cache().last_block_used_ = block;
  777. thread_cache().last_lifecycle_id_seen = lifecycle_id_;
  778. }
  779. int64 lifecycle_id_; // Unique for each arena. Changes on Reset().
  780. google::protobuf::internal::AtomicWord blocks_; // Head of linked list of all allocated blocks
  781. google::protobuf::internal::AtomicWord hint_; // Fast thread-local block access
  782. // Node contains the ptr of the object to be cleaned up and the associated
  783. // cleanup function ptr.
  784. struct Node {
  785. void* elem; // Pointer to the object to be cleaned up.
  786. void (*cleanup)(void*); // Function pointer to the destructor or deleter.
  787. Node* next; // Next node in the list.
  788. };
  789. google::protobuf::internal::AtomicWord cleanup_list_; // Head of a linked list of nodes containing object
  790. // ptrs and cleanup methods.
  791. bool owns_first_block_; // Indicates that arena owns the first block
  792. Mutex blocks_lock_;
  793. void AddBlock(Block* b);
  794. // Access must be synchronized, either by blocks_lock_ or by being called from
  795. // Init()/Reset().
  796. void AddBlockInternal(Block* b);
  797. void* SlowAlloc(size_t n);
  798. Block* FindBlock(void* me);
  799. Block* NewBlock(void* me, Block* my_last_block, size_t n,
  800. size_t start_block_size, size_t max_block_size);
  801. static void* AllocFromBlock(Block* b, size_t n);
  802. template <typename Key, typename T>
  803. friend class Map;
  804. // The arena may save a cookie it receives from the external on_init hook
  805. // and then use it when calling the on_reset and on_destruction hooks.
  806. void* hooks_cookie_;
  807. ArenaOptions options_;
  808. GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Arena);
  809. };
  810. // Defined above for supporting environments without RTTI.
  811. #undef RTTI_TYPE_ID
  812. template<typename T>
  813. const typename Arena::is_arena_constructable<T>::type
  814. Arena::is_arena_constructable<T>::value =
  815. typename Arena::is_arena_constructable<T>::type();
  816. template<typename T>
  817. const typename Arena::is_destructor_skippable<T>::type
  818. Arena::is_destructor_skippable<T>::value =
  819. typename Arena::is_destructor_skippable<T>::type();
  820. } // namespace protobuf
  821. } // namespace google
  822. #endif // GOOGLE_PROTOBUF_ARENA_H__