1 /**
2 * Copyright (c) 2021-2022 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 RUNTIME_MEM_ALLOCATOR_ADAPTER_H
16 #define RUNTIME_MEM_ALLOCATOR_ADAPTER_H
17
18 #include "runtime/include/mem/allocator.h"
19
20 namespace panda::mem {
21
22 template <typename T, AllocScope AllocScopeT>
23 class AllocatorAdapter;
24
25 template <AllocScope AllocScopeT>
26 class AllocatorAdapter<void, AllocScopeT> {
27 public:
28 using value_type = void;
29 using pointer = void *;
30 using const_pointer = const void *;
31
32 template <typename U>
33 struct Rebind {
34 using other = AllocatorAdapter<U, AllocScopeT>;
35 };
36
37 template <typename U>
38 using rebind = Rebind<U>;
39
40 explicit AllocatorAdapter(Allocator *allocator = InternalAllocator<>::GetInternalAllocatorFromRuntime())
allocator_(allocator)41 : allocator_(allocator)
42 {
43 }
44 template <typename U>
45 // NOLINTNEXTLINE(google-explicit-constructor)
AllocatorAdapter(const AllocatorAdapter<U,AllocScopeT> & other)46 AllocatorAdapter(const AllocatorAdapter<U, AllocScopeT> &other) : allocator_(other.allocator_)
47 {
48 }
49 AllocatorAdapter(const AllocatorAdapter &) = default;
50 AllocatorAdapter &operator=(const AllocatorAdapter &) = default;
51
AllocatorAdapter(AllocatorAdapter && other)52 AllocatorAdapter(AllocatorAdapter &&other) noexcept
53 {
54 allocator_ = other.allocator_;
55 other.allocator_ = nullptr;
56 }
57
58 AllocatorAdapter &operator=(AllocatorAdapter &&other) noexcept
59 {
60 allocator_ = other.allocator_;
61 other.allocator_ = nullptr;
62 return *this;
63 }
64
65 ~AllocatorAdapter() = default;
66
67 private:
68 Allocator *allocator_;
69
70 template <typename U, AllocScope TypeT>
71 friend class AllocatorAdapter;
72 };
73
74 template <typename T, AllocScope AllocScopeT = AllocScope::GLOBAL>
75 class AllocatorAdapter {
76 public:
77 using value_type = T;
78 using pointer = T *;
79 using reference = T &;
80 using const_pointer = const T *;
81 using const_reference = const T &;
82 using size_type = size_t;
83 using difference_type = ptrdiff_t;
84
85 template <typename U>
86 struct Rebind {
87 using other = AllocatorAdapter<U, AllocScopeT>;
88 };
89
90 template <typename U>
91 using rebind = Rebind<U>;
92
93 explicit AllocatorAdapter(Allocator *allocator = InternalAllocator<>::GetInternalAllocatorFromRuntime())
allocator_(allocator)94 : allocator_(allocator)
95 {
96 }
97 template <typename U>
98 // NOLINTNEXTLINE(google-explicit-constructor)
AllocatorAdapter(const AllocatorAdapter<U,AllocScopeT> & other)99 AllocatorAdapter(const AllocatorAdapter<U, AllocScopeT> &other) : allocator_(other.allocator_)
100 {
101 }
102 AllocatorAdapter(const AllocatorAdapter &) = default;
103 AllocatorAdapter &operator=(const AllocatorAdapter &) = default;
104
AllocatorAdapter(AllocatorAdapter && other)105 AllocatorAdapter(AllocatorAdapter &&other) noexcept
106 {
107 allocator_ = other.allocator_;
108 other.allocator_ = nullptr;
109 }
110
111 AllocatorAdapter &operator=(AllocatorAdapter &&other) noexcept
112 {
113 allocator_ = other.allocator_;
114 other.allocator_ = nullptr;
115 return *this;
116 }
117
118 ~AllocatorAdapter() = default;
119
120 // NOLINTNEXTLINE(readability-identifier-naming)
121 pointer allocate(size_type size, [[maybe_unused]] const void *hint = nullptr)
122 {
123 // NOLINTNEXTLINE(bugprone-suspicious-semicolon, readability-braces-around-statements)
124 if constexpr (AllocScopeT == AllocScope::GLOBAL) {
125 return allocator_->AllocArray<T>(size);
126 // NOLINTNEXTLINE(readability-misleading-indentation)
127 } else {
128 return allocator_->AllocArrayLocal<T>(size);
129 }
130 }
131
132 // NOLINTNEXTLINE(readability-identifier-naming)
deallocate(pointer ptr,size_type size)133 void deallocate(pointer ptr, [[maybe_unused]] size_type size)
134 {
135 allocator_->Free(ptr);
136 }
137
138 template <typename U, typename... Args>
construct(U * ptr,Args &&...args)139 void construct(U *ptr, Args &&... args) // NOLINT(readability-identifier-naming)
140 {
141 ::new (static_cast<void *>(ptr)) U(std::forward<Args>(args)...);
142 }
143
144 template <typename U>
destroy(U * ptr)145 void destroy(U *ptr) // NOLINT(readability-identifier-naming)
146 {
147 ptr->~U();
148 }
149
150 template <typename U>
151 bool operator==(const AllocatorAdapter<U> &other) const
152 {
153 return this->allocator_ == other.allocator_;
154 }
155
156 template <typename U>
157 bool operator!=(const AllocatorAdapter<U> &other) const
158 {
159 return this->allocator_ != other.allocator_;
160 }
161
162 private:
163 Allocator *allocator_;
164
165 template <typename U, AllocScope TypeT>
166 friend class AllocatorAdapter;
167 };
168
169 template <AllocScope AllocScopeT>
Adapter()170 inline AllocatorAdapter<void, AllocScopeT> Allocator::Adapter()
171 {
172 return AllocatorAdapter<void, AllocScopeT>(this);
173 }
174
175 } // namespace panda::mem
176
177 #endif // RUNTIME_MEM_ALLOCATOR_ADAPTER_H
178