Metall v0.30
A persistent memory allocator for data-centric analytics
 
Loading...
Searching...
No Matches
stl_allocator.hpp
Go to the documentation of this file.
1// Copyright 2020 Lawrence Livermore National Security, LLC and other Metall
2// Project Developers. See the top-level COPYRIGHT file for details.
3//
4// SPDX-License-Identifier: (Apache-2.0 OR MIT)
5
6#ifndef METALL_STL_ALLOCATOR_HPP
7#define METALL_STL_ALLOCATOR_HPP
8
9#include <memory>
10#include <type_traits>
11#include <cassert>
12#include <limits>
13#include <new>
14
15#include <metall/offset_ptr.hpp>
16#include <metall/logger.hpp>
17
18namespace metall {
19
33template <typename T, typename metall_manager_kernel_type>
35 public:
36 // -------------------- //
37 // Public types and static values
38 // -------------------- //
39 using value_type = T;
40 using pointer = typename std::pointer_traits<
41 typename metall_manager_kernel_type::void_pointer>::
42 template rebind<value_type>;
44 typename std::pointer_traits<pointer>::template rebind<const value_type>;
46 typename std::pointer_traits<pointer>::template rebind<void>;
48 typename std::pointer_traits<pointer>::template rebind<const void>;
50 typename std::pointer_traits<pointer>::difference_type;
51 using size_type = typename std::make_unsigned<difference_type>::type;
52 using manager_kernel_type = metall_manager_kernel_type;
53
56 template <typename T2>
60
61 public:
62 // -------------------- //
63 // Constructor & assign operator
64 // -------------------- //
65 // Following manager.hpp in Boost.interprocess, 'explicit' keyword is not used
66 // on purpose although this allocator won't work correctly w/o a valid
67 // manager_kernel_address. The following code will work:
68 //
69 // void func(stl_allocator<int, manager_kernel_type>) {...}
70 // int main() {
71 // manager_kernel_type** ptr = ...
72 // func(ptr); // OK
73 // }
74 //
76 manager_kernel_type *const *const pointer_manager_kernel_address) noexcept
77 : m_ptr_manager_kernel_address(pointer_manager_kernel_address) {}
78
80 template <typename T2>
82 stl_allocator<T2, manager_kernel_type> allocator_instance) noexcept
83 : m_ptr_manager_kernel_address(
84 allocator_instance.get_pointer_to_manager_kernel()) {}
85
87 stl_allocator(const stl_allocator &other) noexcept = default;
88
90 stl_allocator(stl_allocator &&other) noexcept = default;
91
93 ~stl_allocator() noexcept = default;
94
96 stl_allocator &operator=(const stl_allocator &) noexcept = default;
97
99 template <typename T2>
100 stl_allocator &operator=(
101 const stl_allocator<T2, manager_kernel_type> &other) noexcept {
102 m_ptr_manager_kernel_address = other.m_ptr_manager_kernel_address;
103 return *this;
104 }
105
107 stl_allocator &operator=(stl_allocator &&other) noexcept = default;
108
110 template <typename T2>
113 m_ptr_manager_kernel_address = other.m_ptr_manager_kernel_address;
114 return *this;
115 }
116
120 pointer allocate(const size_type n) const { return priv_allocate(n); }
121
125 void deallocate(pointer ptr, const size_type size) const {
126 return priv_deallocate(ptr, size);
127 }
128
131 size_type max_size() const noexcept { return priv_max_size(); }
132
137 template <class... Args>
138 void construct(const pointer &ptr, Args &&...args) const {
139 priv_construct(ptr, std::forward<Args>(args)...);
140 }
141
144 void destroy(const pointer &ptr) const { priv_destroy(ptr); }
145
146 // ---------- This class's unique public functions ---------- //
150 return to_raw_pointer(m_ptr_manager_kernel_address);
151 }
152
153 private:
154 // -------------------- //
155 // Private methods
156 // -------------------- //
157
158 pointer priv_allocate(const size_type n) const {
159 if (priv_max_size() < n) {
160 throw std::bad_array_new_length();
161 }
162
164 logger::out(logger::level::error, __FILE__, __LINE__,
165 "nullptr: cannot access to manager kernel");
166 throw std::bad_alloc();
167 }
168 auto* manager_kernel = *get_pointer_to_manager_kernel();
169 if (!manager_kernel) {
170 logger::out(logger::level::error, __FILE__, __LINE__,
171 "nullptr: cannot access to manager kernel");
172 throw std::bad_alloc();
173 }
174
175 auto addr = pointer(
176 static_cast<value_type *>(manager_kernel->allocate(n * sizeof(T))));
177 if (!addr) {
178 throw std::bad_alloc();
179 }
180
181 return addr;
182 }
183
184 void priv_deallocate(pointer ptr,
185 [[maybe_unused]] const size_type size) const noexcept {
187 logger::out(logger::level::error, __FILE__, __LINE__,
188 "nullptr: cannot access to manager kernel");
189 return;
190 }
191 auto manager_kernel = *get_pointer_to_manager_kernel();
192 if (!manager_kernel) {
193 logger::out(logger::level::error, __FILE__, __LINE__,
194 "nullptr: cannot access to manager kernel");
195 return;
196 }
197 manager_kernel->deallocate(to_raw_pointer(ptr));
198 }
199
200 size_type priv_max_size() const noexcept {
201 return std::numeric_limits<size_type>::max() / sizeof(value_type);
202 }
203
204 template <class... arg_types>
205 void priv_construct(const pointer &ptr, arg_types &&...args) const {
206 ::new ((void *)to_raw_pointer(ptr))
207 value_type(std::forward<arg_types>(args)...);
208 }
209
210 void priv_destroy(const pointer &ptr) const {
211 if (!ptr) {
212 logger::out(logger::level::error, __FILE__, __LINE__,
213 "pointer is nullptr");
214 }
215 (*ptr).~value_type();
216 }
217
218 // -------------------- //
219 // Private fields
220 // -------------------- //
221 private:
222 // (offset)pointer to a raw pointer that points a manager kernel object
223 // allocated in DRAM i.e., offset_ptr<manager_kernel_type *const>
224 typename std::pointer_traits<typename manager_kernel_type::void_pointer>::
225 template rebind<manager_kernel_type *const>
226 m_ptr_manager_kernel_address;
227};
228
229template <typename T, typename kernel>
231 const stl_allocator<T, kernel> &lhd) {
232 // Return true if they point to the same manager kernel
233 return rhd.get_pointer_to_manager_kernel() ==
235}
236
237template <typename T, typename kernel>
239 const stl_allocator<T, kernel> &lhd) {
240 return !(rhd == lhd);
241}
242
243} // namespace metall
244
245#endif // METALL_STL_ALLOCATOR_HPP
static void out(const level lvl, const char *const file_name, const int line_no, const char *const message) noexcept
Log a message.
Definition logger.hpp:35
@ error
Error logger message.
A STL compatible allocator.
Definition stl_allocator.hpp:34
typename std::pointer_traits< pointer >::template rebind< const void > const_void_pointer
Definition stl_allocator.hpp:48
stl_allocator(stl_allocator< T2, manager_kernel_type > allocator_instance) noexcept
Construct a new instance using an instance that has a different T.
Definition stl_allocator.hpp:81
stl_allocator(manager_kernel_type *const *const pointer_manager_kernel_address) noexcept
Definition stl_allocator.hpp:75
void deallocate(pointer ptr, const size_type size) const
Deallocates the storage reference by the pointer ptr.
Definition stl_allocator.hpp:125
void destroy(const pointer &ptr) const
Deconstruct an object of T.
Definition stl_allocator.hpp:144
~stl_allocator() noexcept=default
Destructor.
manager_kernel_type *const * get_pointer_to_manager_kernel() const
Returns a pointer that points to manager kernel.
Definition stl_allocator.hpp:149
pointer allocate(const size_type n) const
Allocates n * sizeof(T) bytes of storage.
Definition stl_allocator.hpp:120
stl_allocator & operator=(stl_allocator &&other) noexcept=default
Move assign operator.
stl_allocator & operator=(stl_allocator< T2, manager_kernel_type > &&other) noexcept
Move assign operator for another T.
Definition stl_allocator.hpp:111
typename std::pointer_traits< pointer >::difference_type difference_type
Definition stl_allocator.hpp:50
T value_type
Definition stl_allocator.hpp:39
typename std::make_unsigned< difference_type >::type size_type
Definition stl_allocator.hpp:51
metall_manager_kernel_type manager_kernel_type
Definition stl_allocator.hpp:52
typename std::pointer_traits< pointer >::template rebind< void > void_pointer
Definition stl_allocator.hpp:46
stl_allocator(const stl_allocator &other) noexcept=default
Copy constructor.
stl_allocator(stl_allocator &&other) noexcept=default
Move constructor.
typename std::pointer_traits< typename metall_manager_kernel_type::void_pointer >::template rebind< value_type > pointer
Definition stl_allocator.hpp:42
void construct(const pointer &ptr, Args &&...args) const
Constructs an object of T.
Definition stl_allocator.hpp:138
typename std::pointer_traits< pointer >::template rebind< const value_type > const_pointer
Definition stl_allocator.hpp:44
size_type max_size() const noexcept
The size of the theoretical maximum allocation size.
Definition stl_allocator.hpp:131
The top level of namespace of Metall.
Definition basic_manager.hpp:22
bool operator!=(const stl_allocator< T, kernel > &rhd, const stl_allocator< T, kernel > &lhd)
Definition stl_allocator.hpp:238
bool operator==(const stl_allocator< T, kernel > &rhd, const stl_allocator< T, kernel > &lhd)
Definition stl_allocator.hpp:230
Makes another allocator type for type T2.
Definition stl_allocator.hpp:57
stl_allocator< T2, manager_kernel_type > other
Definition stl_allocator.hpp:58