Metall  v0.28
A persistent memory allocator for data-centric analytics
fallback_allocator.hpp
Go to the documentation of this file.
1 // Copyright 2024 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_CONTAINER_FALLBACK_ALLOCATOR_HPP
7 #define METALL_CONTAINER_FALLBACK_ALLOCATOR_HPP
8 
9 #include <memory>
10 #include <cstdlib>
11 #include <type_traits>
12 
13 namespace metall::container {
14 
20 template <typename stateful_allocator>
22  // Check if the stateful_allocator takes arugments in its constructor
23  static_assert(!std::is_constructible<stateful_allocator>::value,
24  "The stateful allocator must not be default constructible");
25 
26  private:
27  template <typename T>
28  using other_stateful_allocatorator_type = typename std::allocator_traits<
29  stateful_allocator>::template rebind_alloc<T>;
30 
31  public:
32  // -------------------- //
33  // Public types and static values
34  // -------------------- //
35  using stateful_allocatorator_type = typename std::remove_const<
36  typename std::remove_reference<stateful_allocator>::type>::type;
37 
38  using value_type = typename stateful_allocatorator_type::value_type;
39  using pointer = typename stateful_allocatorator_type::pointer;
40  using const_pointer = typename stateful_allocatorator_type::const_pointer;
41  using void_pointer = typename stateful_allocatorator_type::void_pointer;
43  typename stateful_allocatorator_type::const_void_pointer;
44  using difference_type = typename stateful_allocatorator_type::difference_type;
45  using size_type = typename stateful_allocatorator_type::size_type;
46 
48  template <typename T2>
49  struct rebind {
50  using other =
52  };
53 
54  public:
55  // -------------------- //
56  // Constructor & assign operator
57  // -------------------- //
58 
61  fallback_allocator_adaptor() noexcept : m_stateful_allocatorator(nullptr) {}
62 
65  template <typename stateful_allocatorator_type2,
66  std::enable_if_t<
67  std::is_constructible<stateful_allocator,
68  stateful_allocatorator_type2>::value,
69  int> = 0>
72  allocator_instance) noexcept
73  : m_stateful_allocatorator(allocator_instance.stateful_allocatorator()) {}
74 
77  template <typename stateful_allocatorator_type2,
78  std::enable_if_t<
79  std::is_constructible<stateful_allocator,
80  stateful_allocatorator_type2>::value,
81  int> = 0>
83  stateful_allocatorator_type2 allocator_instance) noexcept
84  : m_stateful_allocatorator(allocator_instance) {}
85 
88  default;
89 
92  default;
93 
96  const fallback_allocator_adaptor &) noexcept = default;
97 
100  template <typename stateful_allocatorator_type2,
101  std::enable_if_t<
102  std::is_constructible<stateful_allocator,
103  stateful_allocatorator_type2>::value,
104  int> = 0>
107  &other) noexcept {
108  m_stateful_allocatorator = other.stateful_allocatorator();
109  return *this;
110  }
111 
113  template <typename stateful_allocatorator_type2,
114  std::enable_if_t<
115  std::is_constructible<stateful_allocator,
116  stateful_allocatorator_type2>::value,
117  int> = 0>
119  const stateful_allocatorator_type2 &allocator_instance) noexcept {
120  m_stateful_allocatorator = allocator_instance;
121  return *this;
122  }
123 
126  fallback_allocator_adaptor &&other) noexcept = default;
127 
130  template <typename stateful_allocatorator_type2,
131  std::enable_if_t<
132  std::is_constructible<stateful_allocator,
133  stateful_allocatorator_type2>::value,
134  int> = 0>
137  &&other) noexcept {
138  m_stateful_allocatorator = std::move(other.stateful_allocatorator());
139  return *this;
140  }
141 
143  template <typename stateful_allocatorator_type2,
144  std::enable_if_t<
145  std::is_constructible<stateful_allocator,
146  stateful_allocatorator_type2>::value,
147  int> = 0>
149  stateful_allocatorator_type2 &&allocator_instance) noexcept {
150  m_stateful_allocatorator = std::move(allocator_instance);
151  return *this;
152  }
153 
157  pointer allocate(const size_type n) const {
158  if (priv_stateful_allocatorator_available()) {
159  return m_stateful_allocatorator.allocate(n);
160  }
161  return priv_fallback_allocate(n);
162  }
163 
167  void deallocate(pointer ptr, const size_type size) const {
168  if (priv_stateful_allocatorator_available()) {
169  m_stateful_allocatorator.deallocate(ptr, size);
170  } else {
171  priv_fallback_deallocate(ptr);
172  }
173  }
174 
177  size_type max_size() const noexcept {
178  return m_stateful_allocatorator.max_size();
179  }
180 
185  template <class... Args>
186  void construct(const pointer &ptr, Args &&...args) const {
187  if (priv_stateful_allocatorator_available()) {
188  m_stateful_allocatorator.construct(ptr, std::forward<Args>(args)...);
189  } else {
190  priv_fallback_construct(ptr, std::forward<Args>(args)...);
191  }
192  }
193 
196  void destroy(const pointer &ptr) const {
197  if (priv_stateful_allocatorator_available()) {
198  m_stateful_allocatorator.destroy(ptr);
199  } else {
200  priv_fallback_destroy(ptr);
201  }
202  }
203 
204  // ---------- This class's unique public functions ---------- //
206  return m_stateful_allocatorator;
207  }
208 
210  return m_stateful_allocatorator;
211  }
212 
213  private:
214  // -------------------- //
215  // Private methods
216  // -------------------- //
217  auto priv_stateful_allocatorator_available() const {
218  return !!(m_stateful_allocatorator.get_pointer_to_manager_kernel());
219  }
220 
221  pointer priv_fallback_allocate(const size_type n) const {
222  if (max_size() < n) {
223  throw std::bad_array_new_length();
224  }
225 
226  void *const addr = std::malloc(n * sizeof(value_type));
227  if (!addr) {
228  throw std::bad_alloc();
229  }
230 
231  return pointer(static_cast<value_type *>(addr));
232  }
233 
234  void priv_fallback_deallocate(pointer ptr) const {
235  std::free(to_raw_pointer(ptr));
236  }
237 
238  void priv_fallback_destroy(pointer ptr) const { (*ptr).~value_type(); }
239 
240  template <class... arg_types>
241  void priv_fallback_construct(const pointer &ptr, arg_types &&...args) const {
242  ::new ((void *)to_raw_pointer(ptr))
243  value_type(std::forward<arg_types>(args)...);
244  }
245 
246  // -------------------- //
247  // Private fields
248  // -------------------- //
249  stateful_allocatorator_type m_stateful_allocatorator;
250 };
251 
252 template <typename stateful_allocatorator_type>
253 inline bool operator==(
256  // Return true if they point to the same manager kernel
257  return rhd.stateful_allocatorator() == lhd.stateful_allocatorator();
258 }
259 
260 template <typename stateful_allocatorator_type>
261 inline bool operator!=(
264  return !(rhd == lhd);
265 }
266 
267 } // namespace metall::container
268 
271 
272 #endif // METALL_CONTAINER_FALLBACK_ALLOCATOR_HPP
A STL compatible allocator which fallbacks to a heap allocator (e.g., malloc()) if its constructor re...
Definition: fallback_allocator.hpp:21
fallback_allocator_adaptor(stateful_allocatorator_type2 allocator_instance) noexcept
Construct a new instance using an instance of any stateful_allocatorator.
Definition: fallback_allocator.hpp:82
fallback_allocator_adaptor & operator=(stateful_allocatorator_type2 &&allocator_instance) noexcept
Move assign operator for any stateful_allocatorator.
Definition: fallback_allocator.hpp:148
fallback_allocator_adaptor & operator=(const fallback_allocator_adaptor &) noexcept=default
Copy assign operator.
pointer allocate(const size_type n) const
Allocates n * sizeof(T) bytes of storage.
Definition: fallback_allocator.hpp:157
fallback_allocator_adaptor & operator=(const fallback_allocator_adaptor< stateful_allocatorator_type2 > &other) noexcept
Copy assign operator, using an instance of fallback_allocator_adaptor with any stateful_allocatorator...
Definition: fallback_allocator.hpp:105
fallback_allocator_adaptor(fallback_allocator_adaptor< stateful_allocatorator_type2 > allocator_instance) noexcept
Construct a new instance using an instance of fallback_allocator_adaptor with any stateful_allocatora...
Definition: fallback_allocator.hpp:70
typename stateful_allocatorator_type::const_pointer const_pointer
Definition: fallback_allocator.hpp:40
fallback_allocator_adaptor & operator=(fallback_allocator_adaptor &&other) noexcept=default
Move assign operator.
fallback_allocator_adaptor(fallback_allocator_adaptor &&other) noexcept=default
Move constructor.
fallback_allocator_adaptor(const fallback_allocator_adaptor &other) noexcept=default
Copy constructor.
typename stateful_allocatorator_type::pointer pointer
Definition: fallback_allocator.hpp:39
void deallocate(pointer ptr, const size_type size) const
Deallocates the storage reference by the pointer ptr.
Definition: fallback_allocator.hpp:167
stateful_allocatorator_type & stateful_allocatorator()
Definition: fallback_allocator.hpp:205
typename stateful_allocatorator_type::size_type size_type
Definition: fallback_allocator.hpp:45
fallback_allocator_adaptor & operator=(const stateful_allocatorator_type2 &allocator_instance) noexcept
Copy assign operator for any stateful_allocatorator.
Definition: fallback_allocator.hpp:118
typename std::remove_const< typename std::remove_reference< stateful_allocator >::type >::type stateful_allocatorator_type
Definition: fallback_allocator.hpp:36
typename stateful_allocatorator_type::value_type value_type
Definition: fallback_allocator.hpp:38
typename stateful_allocatorator_type::const_void_pointer const_void_pointer
Definition: fallback_allocator.hpp:43
typename stateful_allocatorator_type::void_pointer void_pointer
Definition: fallback_allocator.hpp:41
const stateful_allocatorator_type & stateful_allocatorator() const
Definition: fallback_allocator.hpp:209
fallback_allocator_adaptor() noexcept
Default constructor which falls back on the regular allocator (i.e., malloc()).
Definition: fallback_allocator.hpp:61
void construct(const pointer &ptr, Args &&...args) const
Constructs an object of T.
Definition: fallback_allocator.hpp:186
fallback_allocator_adaptor & operator=(fallback_allocator_adaptor< stateful_allocatorator_type2 > &&other) noexcept
Move assign operator, using an instance of fallback_allocator_adaptor with any stateful_allocatorator...
Definition: fallback_allocator.hpp:135
size_type max_size() const noexcept
The size of the theoretical maximum allocation size.
Definition: fallback_allocator.hpp:177
void destroy(const pointer &ptr) const
Deconstruct an object of T.
Definition: fallback_allocator.hpp:196
typename stateful_allocatorator_type::difference_type difference_type
Definition: fallback_allocator.hpp:44
Namespace for Metall container.
bool operator==(const fallback_allocator_adaptor< stateful_allocatorator_type > &rhd, const fallback_allocator_adaptor< stateful_allocatorator_type > &lhd)
Definition: fallback_allocator.hpp:253
bool operator!=(const fallback_allocator_adaptor< stateful_allocatorator_type > &rhd, const fallback_allocator_adaptor< stateful_allocatorator_type > &lhd)
Definition: fallback_allocator.hpp:261
Makes another allocator type for type T2.
Definition: fallback_allocator.hpp:49