1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef PANDA_LIBPANDABASE_MEM_ARENA_H_ 17 #define PANDA_LIBPANDABASE_MEM_ARENA_H_ 18 19 #include "mem.h" 20 21 namespace panda { 22 23 constexpr size_t ARENA_DEFAULT_SIZE = SIZE_1M; 24 constexpr Alignment ARENA_DEFAULT_ALIGNMENT = DEFAULT_ALIGNMENT; 25 26 class Arena { 27 public: 28 Arena(size_t buff_size, void *buff); 29 virtual ~Arena(); 30 DEFAULT_MOVE_SEMANTIC(Arena); 31 DEFAULT_COPY_SEMANTIC(Arena); 32 33 /** 34 * \brief Allocate memory with size \param size and aligned with \param alignment 35 * @param size - size of the allocated memory 36 * @param alignment - alignment of the allocated memory 37 * @return pointer to the allocated memory on success, or nullptr on fail 38 */ 39 void *Alloc(size_t size, Alignment alignment = ARENA_DEFAULT_ALIGNMENT); 40 41 /** 42 * \brief Link this Arena to the \param arena 43 * @param arena - Arena which will be linked as next to the current 44 */ 45 void LinkTo(Arena *arena); 46 47 /** 48 * \brief Clear link to the next arena 49 */ 50 void ClearNextLink(); 51 52 /** 53 * \brief Get next linked Arena 54 * @return next linked Arena or nullptr 55 */ 56 Arena *GetNextArena() const; 57 58 /** 59 * @return Size of free area in the arena 60 */ 61 size_t GetFreeSize() const; 62 63 /** 64 * @return Size of an occupied area in the arena 65 */ 66 size_t GetOccupiedSize() const; 67 68 /** 69 * @return A pointer to the first byte not in the arena 70 */ 71 void *GetArenaEnd() const; 72 73 /** 74 * @return A pointer to the first not allocated byte 75 */ 76 void *GetAllocatedEnd() const; 77 78 /** 79 * @return A pointer to the first allocated byte 80 */ 81 void *GetAllocatedStart() const; 82 83 /** 84 * @return A pointer to the raw memory inside arena 85 */ GetMem()86 void *GetMem() const 87 { 88 return buff_; 89 } 90 GetSize()91 size_t GetSize() const 92 { 93 return size_; 94 } 95 96 /** 97 * \brief Check that \param mem is stored inside this Arena 98 * @return true on success, or false on fail 99 */ 100 bool InArena(const void *mem) const; 101 102 /** 103 * \brief Mark all memory after \param mem as free. Check that \param mem is stored inside this arena. 104 */ 105 void Free(void *mem); 106 107 /** 108 * \brief Set occupied memory size to \param new_size. 109 */ 110 void Resize(size_t new_size); 111 112 /* 113 * \brief Empty arena 114 */ 115 void Reset(); 116 117 /* 118 * \brief Expand arena. The new memory must be located just after the current buffer. 119 * @param extra_buff - pointer to the extra buffer located just after the current. 120 * @param size - the size of the extra buffer 121 */ 122 void ExpandArena(const void *extra_buff, size_t size); 123 124 protected: 125 Arena(size_t buff_size, void *buff, Alignment start_alignment); 126 /** 127 * \brief Fast allocates memory with size \param size 128 * @param size - size of the allocated memory, must be \param alignment aligned 129 * @param alignment - alignment of the allocated memory, used only for debug 130 * @return pointer to the allocated memory on success, or nullptr on fail 131 */ 132 void *AlignedAlloc(size_t size, Alignment alignment); 133 GetStartPos()134 void *GetStartPos() const 135 { 136 return startPos_; 137 } 138 139 private: 140 Arena *next_ = nullptr; 141 void *buff_ = nullptr; 142 void *startPos_ = nullptr; 143 void *curPos_ = nullptr; 144 size_t size_ = 0; 145 }; 146 147 template <Alignment AlignmentT> 148 class AlignedArena : public Arena { 149 public: AlignedArena(size_t buff_size,void * buff)150 AlignedArena(size_t buff_size, void *buff) : Arena(buff_size, buff, AlignmentT) {} 151 152 ~AlignedArena() override = default; 153 154 void *Alloc(size_t size, [[maybe_unused]] Alignment alignment = AlignmentT) 155 { 156 ASSERT(alignment == AlignmentT); 157 return Arena::AlignedAlloc(size, AlignmentT); 158 } 159 160 private: 161 DEFAULT_MOVE_SEMANTIC(AlignedArena); 162 DEFAULT_COPY_SEMANTIC(AlignedArena); 163 }; 164 165 template <Alignment AlignmentT> 166 class DoubleLinkedAlignedArena : public AlignedArena<AlignmentT> { 167 public: DoubleLinkedAlignedArena(size_t buff_size,void * buff)168 DoubleLinkedAlignedArena(size_t buff_size, void *buff) : AlignedArena<AlignmentT>(buff_size, buff) {} 169 170 /** 171 * \brief Link this Arena to the next \param arena 172 * @param arena - Arena which will be linked as next to the current 173 */ LinkNext(DoubleLinkedAlignedArena * arena)174 void LinkNext(DoubleLinkedAlignedArena *arena) 175 { 176 Arena::LinkTo(static_cast<Arena *>(arena)); 177 } 178 179 /** 180 * \brief Link this Arena to the prev \param arena 181 * @param arena - Arena which will be linked as prev to the current 182 */ LinkPrev(DoubleLinkedAlignedArena * arena)183 void LinkPrev(DoubleLinkedAlignedArena *arena) 184 { 185 ASSERT(prev_ == nullptr); 186 prev_ = arena; 187 } 188 189 /** 190 * \brief Return next linked Arena 191 * @return next linked Arena or nullptr 192 */ GetNextArena()193 DoubleLinkedAlignedArena *GetNextArena() const 194 { 195 return static_cast<DoubleLinkedAlignedArena *>(Arena::GetNextArena()); 196 } 197 198 /** 199 * \brief Return prev linked Arena 200 * @return prev linked Arena or nullptr 201 */ GetPrevArena()202 DoubleLinkedAlignedArena *GetPrevArena() const 203 { 204 return prev_; 205 } 206 207 /** 208 * \brief Clears link to the prev arena 209 */ ClearPrevLink()210 void ClearPrevLink() 211 { 212 prev_ = nullptr; 213 } 214 215 ~DoubleLinkedAlignedArena() override = default; 216 217 DEFAULT_MOVE_SEMANTIC(DoubleLinkedAlignedArena); 218 DEFAULT_COPY_SEMANTIC(DoubleLinkedAlignedArena); 219 220 private: 221 DoubleLinkedAlignedArena *prev_ = nullptr; 222 }; 223 224 } // namespace panda 225 226 #endif // PANDA_LIBPANDABASE_MEM_ARENA_H_ 227