• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 #ifndef GOOGLE_PROTOBUF_ARENA_ALLOCATION_POLICY_H__
9 #define GOOGLE_PROTOBUF_ARENA_ALLOCATION_POLICY_H__
10 
11 #include <cstddef>
12 #include <cstdint>
13 
14 namespace google {
15 namespace protobuf {
16 namespace internal {
17 
18 // `AllocationPolicy` defines `Arena` allocation policies. Applications can
19 // customize the initial and maximum sizes for arena allocation, as well as set
20 // custom allocation and deallocation functions. `AllocationPolicy` is for
21 // protocol buffer internal use only, and typically created from a user facing
22 // public configuration class such as `ArenaOptions`.
23 struct AllocationPolicy {
24   static constexpr size_t kDefaultStartBlockSize = 256;
25   static constexpr size_t kDefaultMaxBlockSize = 32 << 10;
26 
27   size_t start_block_size = kDefaultStartBlockSize;
28   size_t max_block_size = kDefaultMaxBlockSize;
29 
30   void* (*block_alloc)(size_t) = nullptr;
31   void (*block_dealloc)(void*, size_t) = nullptr;
32 
IsDefaultAllocationPolicy33   bool IsDefault() const {
34     return start_block_size == kDefaultStartBlockSize &&
35            max_block_size == kDefaultMaxBlockSize && block_alloc == nullptr &&
36            block_dealloc == nullptr;
37   }
38 };
39 
40 // Tagged pointer to an AllocationPolicy.
41 class TaggedAllocationPolicyPtr {
42  public:
TaggedAllocationPolicyPtr()43   constexpr TaggedAllocationPolicyPtr() : policy_(0) {}
44 
TaggedAllocationPolicyPtr(AllocationPolicy * policy)45   explicit TaggedAllocationPolicyPtr(AllocationPolicy* policy)
46       : policy_(reinterpret_cast<uintptr_t>(policy)) {}
47 
set_policy(AllocationPolicy * policy)48   void set_policy(AllocationPolicy* policy) {
49     auto bits = policy_ & kTagsMask;
50     policy_ = reinterpret_cast<uintptr_t>(policy) | bits;
51   }
52 
get()53   AllocationPolicy* get() {
54     return reinterpret_cast<AllocationPolicy*>(policy_ & kPtrMask);
55   }
get()56   const AllocationPolicy* get() const {
57     return reinterpret_cast<const AllocationPolicy*>(policy_ & kPtrMask);
58   }
59 
60   AllocationPolicy& operator*() { return *get(); }
61   const AllocationPolicy& operator*() const { return *get(); }
62 
63   AllocationPolicy* operator->() { return get(); }
64   const AllocationPolicy* operator->() const { return get(); }
65 
is_user_owned_initial_block()66   bool is_user_owned_initial_block() const {
67     return static_cast<bool>(get_mask<kUserOwnedInitialBlock>());
68   }
set_is_user_owned_initial_block(bool v)69   void set_is_user_owned_initial_block(bool v) {
70     set_mask<kUserOwnedInitialBlock>(v);
71   }
72 
get_raw()73   uintptr_t get_raw() const { return policy_; }
74 
75  private:
76   enum : uintptr_t {
77     kUserOwnedInitialBlock = 1,
78   };
79 
80   static constexpr uintptr_t kTagsMask = 7;
81   static constexpr uintptr_t kPtrMask = ~kTagsMask;
82 
83   template <uintptr_t kMask>
get_mask()84   uintptr_t get_mask() const {
85     return policy_ & kMask;
86   }
87   template <uintptr_t kMask>
set_mask(bool v)88   void set_mask(bool v) {
89     if (v) {
90       policy_ |= kMask;
91     } else {
92       policy_ &= ~kMask;
93     }
94   }
95   uintptr_t policy_;
96 };
97 
98 }  // namespace internal
99 }  // namespace protobuf
100 }  // namespace google
101 
102 #endif  // GOOGLE_PROTOBUF_ARENA_ALLOCATION_POLICY_H__
103