1 /**
2 * Copyright (c) 2021-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 #ifndef PANDA_RUNTIME_MEM_RUNSLOTS_STL_ADAPTER_H
16 #define PANDA_RUNTIME_MEM_RUNSLOTS_STL_ADAPTER_H
17
18 #include "runtime/mem/runslots_allocator.h"
19
20 namespace ark::mem {
21
22 // Adapter for use of RunSlotsAllocator in STL containers.
23 template <typename T, typename AllocConfigT, typename LockConfigT>
24 class RunSlotsAllocatorAdapter;
25
26 template <typename AllocConfigT, typename LockConfigT>
27 class RunSlotsAllocatorAdapter<void, AllocConfigT, LockConfigT> {
28 public:
29 // NOLINTNEXTLINE(readability-identifier-naming)
30 using value_type = void;
31 // NOLINTNEXTLINE(readability-identifier-naming)
32 using pointer = void *;
33 // NOLINTNEXTLINE(readability-identifier-naming)
34 using const_pointer = const void *;
35
36 template <typename U>
37 struct Rebind {
38 // NOLINTNEXTLINE(readability-identifier-naming)
39 using other = RunSlotsAllocatorAdapter<U, AllocConfigT, LockConfigT>;
40 };
41
42 template <typename U>
43 // NOLINTNEXTLINE(readability-identifier-naming)
44 using rebind = Rebind<U>;
45
RunSlotsAllocatorAdapter(RunSlotsAllocator<AllocConfigT,LockConfigT> * allocator)46 explicit RunSlotsAllocatorAdapter(RunSlotsAllocator<AllocConfigT, LockConfigT> *allocator) : allocator_(allocator)
47 {
48 }
49 template <typename U>
50 // NOLINTNEXTLINE(google-explicit-constructor)
RunSlotsAllocatorAdapter(const RunSlotsAllocatorAdapter<U,AllocConfigT,LockConfigT> & other)51 RunSlotsAllocatorAdapter(const RunSlotsAllocatorAdapter<U, AllocConfigT, LockConfigT> &other)
52 : allocator_(other.allocator_)
53 {
54 }
55 DEFAULT_COPY_SEMANTIC(RunSlotsAllocatorAdapter);
56 DEFAULT_MOVE_SEMANTIC(RunSlotsAllocatorAdapter);
57 ~RunSlotsAllocatorAdapter() = default;
58
59 private:
60 RunSlotsAllocator<AllocConfigT, LockConfigT> *allocator_;
61
62 template <typename U, typename AllocConfigType, typename LockConfigType>
63 friend class RunSlotsAllocatorAdapter;
64 };
65
66 template <typename T, typename AllocConfigT, typename LockConfigT>
67 class RunSlotsAllocatorAdapter {
68 public:
69 // NOLINTNEXTLINE(readability-identifier-naming)
70 using value_type = T;
71 // NOLINTNEXTLINE(readability-identifier-naming)
72 using pointer = T *;
73 // NOLINTNEXTLINE(readability-identifier-naming)
74 using reference = T &;
75 // NOLINTNEXTLINE(readability-identifier-naming)
76 using const_pointer = const T *;
77 // NOLINTNEXTLINE(readability-identifier-naming)
78 using const_reference = const T &;
79 // NOLINTNEXTLINE(readability-identifier-naming)
80 using size_type = size_t;
81 // NOLINTNEXTLINE(readability-identifier-naming)
82 using difference_type = ptrdiff_t;
83
84 template <typename U>
85 struct Rebind {
86 // NOLINTNEXTLINE(readability-identifier-naming)
87 using other = RunSlotsAllocatorAdapter<U, AllocConfigT, LockConfigT>;
88 };
89
90 template <typename U>
91 // NOLINTNEXTLINE(readability-identifier-naming)
92 using rebind = Rebind<U>;
93
RunSlotsAllocatorAdapter(AllocConfigT * allocator)94 explicit RunSlotsAllocatorAdapter(AllocConfigT *allocator) : allocator_(allocator) {}
95 template <typename U>
96 // NOLINTNEXTLINE(google-explicit-constructor)
RunSlotsAllocatorAdapter(const RunSlotsAllocatorAdapter<U,AllocConfigT,LockConfigT> & other)97 RunSlotsAllocatorAdapter(const RunSlotsAllocatorAdapter<U, AllocConfigT, LockConfigT> &other)
98 : allocator_(other.allocator_)
99 {
100 }
101 RunSlotsAllocatorAdapter(const RunSlotsAllocatorAdapter &) = default;
102 RunSlotsAllocatorAdapter &operator=(const RunSlotsAllocatorAdapter &) = default;
RunSlotsAllocatorAdapter(RunSlotsAllocatorAdapter && other)103 RunSlotsAllocatorAdapter(RunSlotsAllocatorAdapter &&other) noexcept
104 {
105 allocator_ = other.allocator_;
106 other.allocator_ = nullptr;
107 }
108 RunSlotsAllocatorAdapter &operator=(RunSlotsAllocatorAdapter &&other) noexcept
109 {
110 allocator_ = other.allocator_;
111 other.allocator_ = nullptr;
112 return *this;
113 }
114 ~RunSlotsAllocatorAdapter() = default;
115
116 // NOLINTNEXTLINE(readability-identifier-naming)
max_size()117 size_type max_size() const
118 {
119 // NOTE(aemelenko): This solution significantly limits max array size
120 return RunSlots<>::MaxSlotSize() / sizeof(T);
121 }
122
123 // NOLINTNEXTLINE(readability-identifier-naming)
address(reference x)124 pointer address(reference x) const
125 {
126 return &x;
127 }
128 // NOLINTNEXTLINE(readability-identifier-naming)
address(const_reference x)129 const_pointer address(const_reference x) const
130 {
131 return &x;
132 }
133
134 // NOLINTNEXTLINE(readability-identifier-naming)
135 pointer allocate(size_type n,
136 [[maybe_unused]]
137 typename RunSlotsAllocatorAdapter<void, AllocConfigT, LockConfigT>::pointer ptr = nullptr)
138 {
139 ASSERT(n <= max_size());
140 return allocator_->template AllocArray<T>(n);
141 }
142
143 // NOLINTNEXTLINE(readability-identifier-naming)
deallocate(pointer p,size_type n)144 void deallocate([[maybe_unused]] pointer p, [[maybe_unused]] size_type n)
145 {
146 allocator_->Free(static_cast<void *>(p));
147 }
148
149 template <typename U, typename... Args>
150 // NOLINTNEXTLINE(readability-identifier-naming)
construct(U * p,Args &&...args)151 void construct(U *p, Args &&...args)
152 {
153 ::new (static_cast<void *>(p)) U(std::forward<Args>(args)...);
154 }
155 template <typename U>
156 // NOLINTNEXTLINE(readability-identifier-naming)
destroy(U * p)157 void destroy(U *p)
158 {
159 p->~U();
160 }
161
162 private:
163 RunSlotsAllocator<AllocConfigT, LockConfigT> *allocator_ {nullptr};
164
165 template <typename U, typename AllocConfigType, typename LockConfigType>
166 friend class RunSlotsAllocatorAdapter;
167
168 template <typename U>
169 // NOLINTNEXTLINE(readability-redundant-declaration)
170 friend inline bool operator==(const RunSlotsAllocatorAdapter &,
171 const RunSlotsAllocatorAdapter<U, AllocConfigT, LockConfigT> &rhs);
172 };
173
174 template <typename T, typename AllocConfigT, typename LockConfigT>
175 inline bool operator==(const RunSlotsAllocatorAdapter<T, AllocConfigT, LockConfigT> &lhs,
176 const RunSlotsAllocatorAdapter<T, AllocConfigT, LockConfigT> &rhs)
177 {
178 return lhs.allocator_ == rhs.allocator_;
179 }
180
181 template <typename T, typename AllocConfigT, typename LockConfigT>
182 inline bool operator!=(const RunSlotsAllocatorAdapter<T, AllocConfigT, LockConfigT> &lhs,
183 const RunSlotsAllocatorAdapter<T, AllocConfigT, LockConfigT> &rhs)
184 {
185 return !(lhs == rhs);
186 }
187
188 template <typename AllocConfigT, typename LockConfigT>
Adapter()189 inline RunSlotsAllocatorAdapter<void, AllocConfigT, LockConfigT> RunSlotsAllocator<AllocConfigT, LockConfigT>::Adapter()
190 {
191 return RunSlotsAllocatorAdapter<void, AllocConfigT, LockConfigT>(this);
192 }
193
194 } // namespace ark::mem
195
196 #endif // PANDA_RUNTIME_MEM_RUNSLOTS_STL_ADAPTER_H
197