Allocator Builder
Policy Based C++ Template Allocator Library
 All Classes Functions Variables Enumerations Enumerator Groups Pages
affix_allocator.hpp
1 //
3 // Copyright 2014 Felix Petriconi
4 //
5 // License: http://boost.org/LICENSE_1_0.txt, Boost License 1.0
6 //
7 // Authors: http://petriconi.net, Felix Petriconi
8 //
10 #pragma once
11 
12 #include "allocator_base.hpp"
13 #include "internal/reallocator.hpp"
14 #include "internal/affix_helper.hpp"
15 
16 #ifdef _MSC_VER
17 #pragma warning(push)
18 #pragma warning(disable : 4345)
19 #endif
20 
21 namespace alb {
22  inline namespace v_100 {
23 
44  template <class Allocator, typename Prefix, typename Sufix = affix_helper::no_affix>
46  {
47  Allocator allocator_;
48 
49  constexpr Prefix *inner_to_prefix(const block &b) const noexcept
50  {
51  return static_cast<Prefix *>(b.ptr);
52  }
53 
54  constexpr Sufix *inner_to_sufix(const block &b) const noexcept
55  {
56  return reinterpret_cast<Sufix*>(static_cast<char*>(b.ptr) + b.length - sufix_size);
57  }
58 
59  constexpr block to_inner_block(const block &b) const noexcept
60  {
61  return { static_cast<char *>(b.ptr) - prefix_size, b.length + prefix_size + sufix_size };
62  }
63 
64  constexpr block to_outer_block(const block &b) const noexcept
65  {
66  return { static_cast<char *>(b.ptr) + prefix_size, b.length - prefix_size - sufix_size };
67  }
68 
69  public:
70  affix_allocator(const affix_allocator &) = delete;
71  affix_allocator &operator=(const affix_allocator &) = delete;
72 
73  static constexpr bool supports_truncated_deallocation = Allocator::supports_truncated_deallocation;
74  static constexpr unsigned alignment = Allocator::alignment;
75 
76  using allocator = Allocator;
77  using prefix = Prefix;
78  using sufix = Sufix;
79 
80  static constexpr size_t prefix_size =
81  std::is_same<Prefix, affix_helper::no_affix>::value ? 0 : internal::round_to_alignment(alignment, sizeof(Prefix));
82 
83  static constexpr size_t sufix_size =
84  std::is_same<Sufix, affix_helper::no_affix>::value ? 0 : internal::round_to_alignment(alignment, sizeof(Sufix));
85 
86  static constexpr size_t good_size(size_t n) {
87  return Allocator::good_size(n);
88  }
89 
90  affix_allocator() noexcept
91  {}
92 
93  affix_allocator(affix_allocator &&x) = default;
94 
95  affix_allocator &operator=(affix_allocator &&x) = default;
96 
103  constexpr Prefix *outer_to_prefix(const block &b) const noexcept
104  {
105  return b ? reinterpret_cast<Prefix *>(static_cast<char*>(b.ptr) - prefix_size) : nullptr;
106  }
107 
114  constexpr Sufix *outer_to_sufix(const block &b) const noexcept
115  {
116  return b ? (reinterpret_cast<Sufix*>(static_cast<char *>(b.ptr) + b.length)) : nullptr;
117  }
118 
128  block allocate(size_t n) noexcept
129  {
130  block result;
131  if (n == 0) {
132  return result;
133  }
134 
135  auto innerMem = allocator_.allocate(prefix_size + n + sufix_size);
136  if (innerMem) {
137  if (prefix_size > 0) {
138  affix_helper::create_affix_in_place<Prefix>(inner_to_prefix(innerMem), *this);
139  }
140  if (sufix_size > 0) {
141  affix_helper::create_affix_in_place<Sufix>(inner_to_sufix(innerMem), *this);
142  }
143  result = to_outer_block(innerMem);
144  return result;
145  }
146  return result;
147  }
148 
154  void deallocate(block &b) noexcept
155  {
156  if (!b) {
157  return;
158  }
159  if (prefix_size > 0) {
160  outer_to_prefix(b)->~Prefix();
161  }
162  if (sufix_size > 0) {
163  outer_to_sufix(b)->~Sufix();
164  }
165  auto innerBlock(to_inner_block(b));
166  allocator_.deallocate(innerBlock);
167  b.reset();
168  }
169 
175  template <typename U = Allocator>
176  typename std::enable_if<traits::has_owns<U>::value, bool>::type
177  owns(const block &b) const noexcept
178  {
179  return b && allocator_.owns(to_inner_block(b));
180  }
181 
190  bool reallocate(block &b, size_t n) noexcept
191  {
192  if (internal::is_reallocation_handled_default(*this, b, n)) {
193  return true;
194  }
195  auto innerBlock = to_inner_block(b);
196 
197  // Remember the old Sufix in case that it is available, because it must
198  // be later placed to the new position
200  oldSufix.store(outer_to_sufix(b));
201 
202  if (allocator_.reallocate(innerBlock, n + prefix_size + sufix_size)) {
203  oldSufix.unload(inner_to_sufix(innerBlock));
204  b = to_outer_block(innerBlock);
205  return true;
206  }
207  return false;
208  }
209 
218  template <typename U = Allocator>
219  typename std::enable_if<traits::has_expand<U>::value, bool>::type
220  expand(block &b, size_t delta) noexcept
221  {
222  if (delta == 0) {
223  return true;
224  }
225 
226  if (!b) {
227  b = allocate(delta);
228  return static_cast<bool>(b);
229  }
230 
231  auto oldBlock = b;
232  auto innerBlock = to_inner_block(b);
233 
234  if (allocator_.expand(innerBlock, delta)) {
235  if (sufix_size > 0) {
236  new (inner_to_sufix(innerBlock)) Sufix(*outer_to_sufix(oldBlock));
237  }
238  b = to_outer_block(innerBlock);
239  return true;
240  }
241  return false;
242  }
243  };
244 
245  namespace traits {
252  template <class Allocator, typename T> struct affix_extractor {
253  static constexpr T *prefix(Allocator &, const block &) noexcept
254  {
255  return nullptr;
256  }
257  static constexpr T *sufix(Allocator &, const block &) noexcept
258  {
259  return nullptr;
260  }
261  };
262 
263  template <class A, typename Prefix, typename Sufix, typename T>
264  struct affix_extractor<affix_allocator<A, Prefix, Sufix>, T> {
265  static constexpr Prefix *prefix(affix_allocator<A, Prefix, Sufix> &allocator, const block &b) noexcept
266  {
267  return allocator.outer_to_prefix(b);
268  }
269  static constexpr Sufix *sufix(affix_allocator<A, Prefix, Sufix> &allocator, const block &b) noexcept
270  {
271  return allocator.outer_to_sufix(b);
272  }
273  };
274  }
275  }
276  using namespace v_100;
277 }
278 
279 #ifdef _MSC_VER
280 #pragma warning(pop)
281 #endif
std::enable_if< traits::has_owns< U >::value, bool >::type owns(const block &b) const noexcept
void reset() noexcept
block allocate(size_t n) noexcept
size_t length
This describes the length of the reserved bytes.
constexpr size_t round_to_alignment(size_t basis, size_t n) noexcept
bool reallocate(block &b, size_t n) noexcept
void * ptr
This points to the start address of the described memory block.
constexpr Sufix * outer_to_sufix(const block &b) const noexcept
std::enable_if< traits::has_expand< U >::value, bool >::type expand(block &b, size_t delta) noexcept
constexpr Prefix * outer_to_prefix(const block &b) const noexcept
void deallocate(block &b) noexcept