1 /*
2  * Copyright (c) 2024 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 CORE_UTIL_LINEAR_ALLOCATOR_H
17 #define CORE_UTIL_LINEAR_ALLOCATOR_H
18 
19 #include <cstdint>
20 #include <cstdlib>
21 #include <memory>
22 
23 #include <base/containers/unique_ptr.h>
24 #include <core/namespace.h>
25 
CORE_BEGIN_NAMESPACE()26 CORE_BEGIN_NAMESPACE()
27 class LinearAllocator {
28 public:
29     explicit LinearAllocator(size_t size) : size_(size), data_(BASE_NS::make_unique<uint8_t[]>(size))
30     {
31         Reset();
32     }
33 
34     LinearAllocator(size_t size, size_t alignment)
35         : size_(size), alignment_(alignment), data_(BASE_NS::make_unique<uint8_t[]>(size_ + alignment_ - 1))
36     {
37         Reset();
38     }
39 
40     ~LinearAllocator() = default;
41 
42     template<typename T>
43     T* Allocate()
44     {
45         return static_cast<T*>(Allocate(sizeof(T), alignof(T)));
46     }
47 
48     void* Allocate(size_t size)
49     {
50         return Allocate(size, 1);
51     }
52 
53     void* Allocate(size_t size, size_t alignment)
54     {
55         if (std::align(alignment, size, current_, free_)) {
56             void* result = current_;
57 
58             current_ = static_cast<char*>(current_) + size;
59             free_ -= size;
60             return result;
61         }
62 
63         return nullptr;
64     }
65 
66     inline void Reset()
67     {
68         current_ = data_.get();
69         free_ = size_;
70         auto allocationSize = size_ + alignment_ - 1;
71         std::align(alignment_, 1, current_, allocationSize);
72     }
73 
74     inline size_t GetByteSize() const
75     {
76         return size_;
77     }
78 
79     inline size_t GetCurrentByteSize() const
80     {
81         return size_ - free_;
82     }
83 
84     inline size_t GetAlignment() const
85     {
86         return alignment_;
87     }
88 
89 private:
90     size_t const size_ { 0 };
91     size_t const alignment_ = 1;
92     size_t free_ { 0 };
93 
94     BASE_NS::unique_ptr<uint8_t[]> data_;
95     void* current_ { nullptr };
96 };
97 CORE_END_NAMESPACE()
98 
99 #endif // CORE_UTIL_LINEAR_ALLOCATOR_H
100