LCOV - code coverage report
Current view: top level - third_party/protobuf/src/google/protobuf - arena.h (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 2 51 3.9 %
Date: 2015-10-10 Functions: 0 110 0.0 %

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

Generated by: LCOV version 1.10