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