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