Allocator Builder
Policy Based C++ Template Allocator Library
 All Classes Functions Variables Enumerations Enumerator Groups Pages
allocator_base.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 "internal/traits.hpp"
13 #include "internal/array_creation_evaluator.hpp"
14 #include "stl_allocator_adapter.hpp"
15 #include <utility>
16 #include <type_traits>
17 #include <stddef.h>
18 #include <memory>
19 
20 namespace alb {
21  inline namespace v_100 {
26  struct block {
27  block() noexcept
28  : ptr(nullptr)
29  , length(0)
30  {
31  }
32 
33  block(void *ptr, size_t length) noexcept
34  : ptr(ptr)
35  , length(length)
36  {
37  }
38 
39  block(block &&x) noexcept
40  {
41  *this = std::move(x);
42  }
43 
44  block &operator=(block &&x) noexcept
45  {
46  ptr = x.ptr;
47  length = x.length;
48  x.reset();
49  return *this;
50  }
51 
52  block &operator=(const block &x) noexcept = default;
53  block(const block &x) noexcept = default;
54 
60  {
61  }
62 
66  void reset() noexcept
67  {
68  ptr = nullptr;
69  length = 0;
70  }
71 
75  explicit operator bool() const
76  {
77  return length != 0;
78  }
79 
80  bool operator==(const block &rhs) const
81  {
82  return ptr == rhs.ptr && length == rhs.length;
83  }
84 
86  void *ptr;
87 
89  size_t length;
90  };
91 
92 
93  template< class T, class Allocator, class... Args>
94  std::shared_ptr<T> make_shared(const Allocator& alloc, Args&&... args)
95  {
96  using LocalAllocator = typename std_allocator_adapter<T, Allocator>;
97  auto localAllocator = LocalAllocator(alloc);
98  return std::allocate_shared<T, LocalAllocator>(localAllocator, std::forward<Args>(args)...);
99  }
100 
106  template <typename Allocator>
107  class deleter
108  {
109  Allocator *allocator_;
110  size_t extend_;
111  public:
112  using allocator = Allocator;
113 
114  deleter() : allocator_(nullptr), extend_(1) {}
115 
116  explicit deleter(Allocator& a)
117  : allocator_(a)
118  {}
119 
120  void set_allocator(Allocator& a)
121  {
122  allocator_ = &a;
123  }
124 
125  void set_extend(size_t e)
126  {
127  extend_ = e;
128  }
129 
130  template <typename U>
131  void operator()(U* p) {
132  if (p) {
133  // in case that p is an array of U, all objects must be destroyed
134  for (auto i = 0u; i < extend_; ++i) { p[i].~U(); }
135  // The C++ standard allows that the allocated memory position is different to the
136  // pointer of the first element. In this case
137  auto realMemoryLocation = (extend_ == 1 || std::is_trivially_destructible<U>::value)? p :
138  (static_cast<void*>(reinterpret_cast<char*>(p) - helpers::array_offset()));
139 
140  block pseudoBlock(realMemoryLocation , 1 );
141  auto size_prefix = allocator_->outer_to_prefix(pseudoBlock);
142  block realBlock(realMemoryLocation, *size_prefix);
143  allocator_->deallocate(realBlock);
144  }
145  }
146  };
147 
148  template<class T, typename Allocator>
149  struct _Unique_if
150  {
151  typedef std::unique_ptr<T, deleter<Allocator>> _Single_object;
152  };
153 
154  template<class T, typename Allocator>
155  struct _Unique_if < T[], Allocator > {
156  typedef std::unique_ptr<T[], deleter<Allocator>> _Unknown_bound;
157  };
158 
159  template<class T, size_t N, typename Allocator>
160  struct _Unique_if < T[N], Allocator > {
161  typedef void _Known_bound;
162  };
163 
164  template<class T, class Allocator, class... Args>
165  typename _Unique_if<T, Allocator>::_Single_object make_unique(Allocator& a, Args&&... args) {
166  auto b = a.allocate(sizeof(T));
167  if (b)
168  {
169  auto p = a.outer_to_prefix(b);
170  *p = static_cast<typename Allocator::prefix>(b.length);
171  auto result = std::unique_ptr<T, deleter<Allocator>>(new (b.ptr) T(std::forward<Args>(args)...));
172  result.get_deleter().set_allocator(a);
173  return result;
174  }
175  return std::unique_ptr<T, deleter<Allocator>>();
176  }
177 
178  template<class T, class Allocator>
179  typename _Unique_if<T, Allocator>::_Unknown_bound make_unique(Allocator& a, size_t n) {
180  typedef typename std::remove_extent<T>::type U;
181 
182  auto b = a.allocate(sizeof(U) * n + helpers::array_offset());
183  if (b)
184  {
185  auto p = a.outer_to_prefix(b);
186  *p = static_cast<typename Allocator::prefix>(b.length);
187  auto result = std::unique_ptr<U[], deleter<Allocator>>(new (b.ptr) U[n]);
188  result.get_deleter().set_allocator(a);
189  result.get_deleter().set_extend(n);
190  return result;
191  }
192  return std::unique_ptr<T, deleter<Allocator>>();
193  }
194 
195  template<class T, class Allocator, class... Args>
196  typename _Unique_if<T, deleter<Allocator>>::_Known_bound make_unique(Allocator&, Args&&...) = delete;
197 
198 
199  namespace internal {
200 
207  void block_copy(const block &source, block &destination) noexcept;
208 
213  inline constexpr size_t round_to_alignment(size_t basis, size_t n) noexcept
214  {
215  // auto remainder = n % basis;
216  // return n + ((remainder == 0) ? 0 : (basis - remainder));
217  return n + ((n % basis == 0) ? 0 : (basis - n % basis));
218  }
219 
220  } // namespace Helper
221  }
222  using namespace v_100;
223 }
void reset() noexcept
void block_copy(const block &source, block &destination) 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
void * ptr
This points to the start address of the described memory block.