casacore
Loading...
Searching...
No Matches
Allocator.h
Go to the documentation of this file.
1// # Allocator.h:
2// # Copyright (C) 2015
3// # National Astronomical Observatory of Japan
4// # 2-21-1, Osawa, Mitaka, Tokyo, 181-8588, Japan.
5// #
6// # This library is free software; you can redistribute it and/or modify it
7// # under the terms of the GNU Library General Public License as published by
8// # the Free Software Foundation; either version 2 of the License, or (at your
9// # option) any later version.
10// #
11// # This library is distributed in the hope that it will be useful, but WITHOUT
12// # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13// # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
14// # License for more details.
15// #
16// # You should have received a copy of the GNU Library General Public License
17// # along with this library; if not, write to the Free Software Foundation,
18// # Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
19// #
20// # Correspondence concerning AIPS++ should be addressed as follows:
21// # Internet email: casa-feedback@nrao.edu.
22// # Postal address: AIPS++ Project Office
23// # National Radio Astronomy Observatory
24// # 520 Edgemont Road
25// # Charlottesville, VA 22903-2475 USA
26
27#ifndef CASA_CONTAINERS_ALLOCATOR_H_
28#define CASA_CONTAINERS_ALLOCATOR_H_
29
30#include <casacore/casa/config.h>
31#include <casacore/casa/aips.h>
32#include <casacore/casa/Utilities/DataType.h>
33#include <casacore/casa/Arrays/ArrayFwd.h>
34
35#include <cstddef>
36#include <cstdlib>
37#include <memory>
38#include <new>
39#include <typeinfo>
40#include <type_traits>
41
42namespace casacore { // # NAMESPACE CASACORE - BEGIN
43
44#ifndef CASA_DEFAULT_ALIGNMENT
45#define CASA_DEFAULT_ALIGNMENT (32UL) // AVX/AVX2 alignment
46#endif
47
48// <summary>
49// A global enum used by some Array/Block constructors.
50// </summary>
51// <synopsis>
52// ArrayInitPolicy is used in functions where an array is allocated/resized.
53// </synopsis>
55 public:
56 Bool operator==(ArrayInitPolicy const &other) { return init == other.init; }
57 Bool operator!=(ArrayInitPolicy const &other) { return init != other.init; }
58
59 private:
61 explicit constexpr ArrayInitPolicy(bool v) : init(v) {}
62 friend struct ArrayInitPolicies;
63};
64
66 // Don't initialize elements in the array. (The array will be explicitly filled with values other
67 // than the default value.)
68 static constexpr ArrayInitPolicy NO_INIT = ArrayInitPolicy(false);
69 // Initialize all elements in the array with the default value.
70 static constexpr ArrayInitPolicy INIT = ArrayInitPolicy(true);
71};
72
73template <typename T>
74using std11_allocator = std::allocator<T>;
75
76template <typename T, size_t ALIGNMENT = CASA_DEFAULT_ALIGNMENT>
79 using size_type = typename Super::size_type;
80 using difference_type = typename Super::difference_type;
81 using pointer = T *;
82 using const_pointer = const T *;
83 using reference = T &;
84 using const_reference = const T &;
85 using value_type = typename Super::value_type;
86
87 static constexpr size_t alignment = ALIGNMENT;
88
89 template <typename TOther>
93 casacore_allocator() noexcept = default;
94
95 casacore_allocator(const casacore_allocator &other) noexcept = default;
96
97 template <typename TOther>
98 casacore_allocator(const casacore_allocator<TOther> &) noexcept {}
99
100 ~casacore_allocator() noexcept = default;
101
102 pointer allocate(size_type elements, const void * = 0) {
103 if (elements > std::allocator_traits<casacore_allocator>::max_size(*this)) {
104 throw std::bad_alloc();
105 }
106 void *memptr = 0;
107 int result = posix_memalign(&memptr, ALIGNMENT, sizeof(T) * elements);
108 if (result != 0) {
109 throw std::bad_alloc();
110 }
111 return static_cast<pointer>(memptr);
112 }
113
114 void deallocate(pointer ptr, size_type) { free(ptr); }
115};
116
117template <typename T, size_t ALIGNMENT>
120 return true;
121}
122
123template <typename T, size_t ALIGNMENT>
126 return false;
127}
128
129template <typename T>
132 using size_type = typename Super::size_type;
133 using difference_type = typename Super::difference_type;
134 using pointer = T *;
135 using const_pointer = const T *;
136 using reference = T &;
137 using const_reference = const T &;
138 using value_type = typename Super::value_type;
139
140 template <typename TOther>
144 new_del_allocator() noexcept {}
145
146 new_del_allocator(const new_del_allocator &other) noexcept : Super(other) {}
147
148 template <typename TOther>
150
151 ~new_del_allocator() noexcept {}
152
153 pointer allocate(size_type elements, const void * = 0) {
154 if (elements > std::allocator_traits<new_del_allocator>::max_size(*this)) {
155 throw std::bad_alloc();
156 }
157 return new T[elements];
158 }
159
160 void deallocate(pointer ptr, size_type) { delete[] ptr; }
161 template <typename U, typename... Args>
162 void construct(U *, Args &&...) {} // do nothing because new T[] does
163 template <typename U>
164 void construct(U *ptr, U &&value) {
165 *ptr = value; // because *ptr was already contructed by new[].
166 }
167 template <typename U>
168 void construct(U *ptr, U &value) {
169 *ptr = value; // because *ptr was already contructed by new[].
170 }
171 template <typename U>
172 void construct(U *ptr, U const &value) {
173 *ptr = value; // because *ptr was already contructed by new[].
174 }
175
176 template <typename U>
177 void destroy(U *) {} // do nothing because delete[] will do.
178};
179
180template <typename T>
182 return true;
183}
184
185template <typename T>
187 return false;
188}
189
190template <typename T>
191class Block;
192
194 template <typename T>
195 friend class AbstractAllocator;
196 template <typename T, typename Sub>
197 friend class BaseAllocator;
198 template <typename T>
199 friend class Block;
200
201 template <typename T2>
203 using size_type = typename std::allocator<T2>::size_type;
204 using value_type = typename std::allocator<T2>::value_type;
205 using pointer = T2 *;
206 using const_pointer = const T2 *;
207
208 virtual pointer allocate(size_type elements, const void *ptr = 0) = 0;
209 virtual void deallocate(pointer ptr, size_type size) = 0;
210
211 virtual void construct(pointer ptr, size_type n, const_pointer src) = 0;
212 virtual void construct(pointer ptr, size_type n, value_type const &initial_value) = 0;
213 virtual void construct(pointer ptr, size_type n) = 0;
214 virtual void destroy(pointer ptr, size_type n) = 0;
215 virtual std::type_info const &allocator_typeid() const = 0;
216 virtual ~BulkAllocator() {}
217 };
218
219 template <typename Allocator>
220 struct BulkAllocatorImpl : public BulkAllocator<typename Allocator::value_type> {
221 typedef typename Allocator::size_type size_type;
222 typedef typename Allocator::pointer pointer;
223 typedef typename Allocator::const_pointer const_pointer;
224 typedef typename Allocator::value_type value_type;
225 virtual pointer allocate(size_type elements, const void *ptr = 0) override {
226 return allocator.allocate(elements, ptr);
227 }
228 virtual void deallocate(pointer ptr, size_type size) override {
229 allocator.deallocate(ptr, size);
230 }
231
232 virtual void construct(pointer ptr, size_type n, const_pointer src) override {
233 size_type i = 0;
234 try {
235 for (i = 0; i < n; ++i) {
236 std::allocator_traits<Allocator>::construct(allocator, &ptr[i], src[i]);
237 }
238 } catch (...) {
239 destroy(ptr, i); // rollback constructions
240 throw;
241 }
242 }
243 virtual void construct(pointer ptr, size_type n, value_type const &initial_value) override {
244 size_type i = 0;
245 try {
246 for (i = 0; i < n; ++i) {
247 std::allocator_traits<Allocator>::construct(allocator, &ptr[i], initial_value);
248 }
249 } catch (...) {
250 destroy(ptr, i); // rollback constructions
251 throw;
252 }
253 }
254 virtual void construct(pointer ptr, size_type n) override {
255 size_type i = 0;
256 try {
257 for (i = 0; i < n; ++i) {
258 std::allocator_traits<Allocator>::construct(allocator, &ptr[i]);
259 }
260 } catch (...) {
261 destroy(ptr, i); // rollback constructions
262 throw;
263 }
264 }
265 virtual void destroy(pointer ptr, size_type n) override {
266 for (size_type i = n; i > 0;) {
267 --i;
268 try {
269 std::allocator_traits<Allocator>::destroy(allocator, &ptr[i]);
270 } catch (...) {
271 // Destructor should not raise any exception.
272 }
273 }
274 }
275 virtual std::type_info const &allocator_typeid() const override { return typeid(Allocator); }
276 virtual ~BulkAllocatorImpl() override {}
277
278 private:
279 static Allocator allocator;
280 };
281
282 template <typename Allocator>
286
287 template <typename Allocator>
289 // Because this function gets called from destructors of statically allocated objects that get
290 // destructed after the program finishes, the allocator is constructed in a static storage space
291 // and is never destructed.
292 alignas(BulkAllocatorImpl<Allocator>) static std::byte
294 static BulkAllocatorImpl<Allocator> *ptr =
295 new (reinterpret_cast<BulkAllocatorImpl<Allocator> *>(&storage))
297 return ptr;
298 }
299
300 // <summary>Allocator specifier</summary>
301 // <synopsis>
302 // This class is just used to avoid ambiguity between overloaded functions.
303 // </synopsis>
304 template <typename T>
305 struct AllocSpec {
307 explicit AllocSpec(BulkAllocator<T> *alloc) : allocator(alloc) {}
308 };
309};
310
311template <typename Allocator>
313
314template <typename T>
316 public:
317 typedef T value_type;
319
320 protected:
322 friend class Array<T>;
323 friend class Block<T>;
324
326};
327
328template <typename T, typename Sub>
330 public:
331 typedef T value_type;
332 typedef Sub facade_type;
333 virtual ~BaseAllocator() {}
334
335 protected:
337
341};
342
343// An allocator behaves like operator new[]/delete[].
344// Because it is impossible to decouple construction/destruction from allocation/deallocation with
345// this allocator, it is discouraged to use this allocator. Use <src>DefaultAllocator<T></src> or
346// <src>AlignedAllocator<T, ALIGNMENT></src> as possible. This allocator is provided only for
347// compatibility for calling <src>Array::takeStorage(), Block::replaceStorage(), Block(size_t, T *&,
348// Bool)</src> etc. with a storage allocated by operator new[].
349template <typename T>
350class NewDelAllocator : public BaseAllocator<T, NewDelAllocator<T>> {
351 public:
353 // an instance of this allocator.
355
356 protected:
358};
359template <typename T>
361
362// An allocator which allocates aligned memory.
363template <typename T, size_t ALIGNMENT = CASA_DEFAULT_ALIGNMENT>
364class AlignedAllocator : public BaseAllocator<T, AlignedAllocator<T, ALIGNMENT>> {
365 public:
367 // an instance of this allocator.
369
370 protected:
372};
373template <typename T, size_t ALIGNMENT>
375
376// An aligned allocator with the default alignment.
377template <typename T>
379 public:
381 // an instance of this allocator.
383
384 protected:
386};
387template <typename T>
389
390// <summary>Allocator specifier</summary>
391// <synopsis>
392// This class is just used to avoid ambiguity between overloaded functions.
393// </synopsis>
394template <typename T>
395struct AllocSpec {
396 typedef T type;
397 static AllocSpec<T> const value;
398};
399template <typename T>
401
402} // namespace casacore
403
404#endif /* CASA_CONTAINERS_ALLOCATOR_H_ */
virtual Allocator_private::BulkAllocator< T > * getAllocator() const =0
An allocator which allocates aligned memory.
Definition Allocator.h:364
static AlignedAllocator< T, CASA_DEFAULT_ALIGNMENT > value
Definition Allocator.h:368
casacore_allocator< T, ALIGNMENT > type
Definition Allocator.h:366
static BulkAllocator< typename Allocator::value_type > * get_allocator()
Definition Allocator.h:283
static BulkAllocatorImpl< Allocator > * get_allocator_raw()
Definition Allocator.h:288
friend class AbstractAllocator
Definition Allocator.h:195
Bool operator==(ArrayInitPolicy const &other)
Definition Allocator.h:56
friend struct ArrayInitPolicies
Definition Allocator.h:62
constexpr ArrayInitPolicy(bool v)
Definition Allocator.h:61
Bool operator!=(ArrayInitPolicy const &other)
Definition Allocator.h:57
virtual Allocator_private::BulkAllocator< T > * getAllocator() const override
Definition Allocator.h:338
An aligned allocator with the default alignment.
Definition Allocator.h:378
static DefaultAllocator< T > value
an instance of this allocator.
Definition Allocator.h:382
AlignedAllocator< T >::type type
Definition Allocator.h:380
An allocator behaves like operator new[]/delete[].
Definition Allocator.h:350
new_del_allocator< T > type
Definition Allocator.h:352
static NewDelAllocator< T > value
an instance of this allocator.
Definition Allocator.h:354
bool operator==(const String &x, const String &y)
Global comparison operators.
Definition String.h:849
free(pool)
For temporary backward namespace compatibility, use casa as alias for casacore.
Definition mainpage.dox:28
T * storage()
If you really, really, need a "raw" pointer to the beginning of the storage area this will give it to...
Definition Block.h:559
bool Bool
Define the standard types used by Casacore.
Definition aipstype.h:40
size_t size() const
Definition Block.h:566
bool operator!=(const String &x, const String &y)
Definition String.h:850
NewDelAllocator< T > NewDelAllocator< T >::value
Definition Allocator.h:360
std::allocator< T > std11_allocator
Definition Allocator.h:74
Allocator specifier.
Definition Allocator.h:395
static AllocSpec< T > const value
Definition Allocator.h:397
AllocSpec(BulkAllocator< T > *alloc)
Definition Allocator.h:307
virtual void construct(pointer ptr, size_type n, const_pointer src) override
Definition Allocator.h:232
virtual void construct(pointer ptr, size_type n, value_type const &initial_value) override
Definition Allocator.h:243
virtual void construct(pointer ptr, size_type n) override
Definition Allocator.h:254
virtual void deallocate(pointer ptr, size_type size) override
Definition Allocator.h:228
virtual void destroy(pointer ptr, size_type n) override
Definition Allocator.h:265
virtual std::type_info const & allocator_typeid() const override
Definition Allocator.h:275
virtual pointer allocate(size_type elements, const void *ptr=0) override
Definition Allocator.h:225
virtual std::type_info const & allocator_typeid() const =0
typename std::allocator< T2 >::size_type size_type
Definition Allocator.h:203
virtual pointer allocate(size_type elements, const void *ptr=0)=0
virtual void deallocate(pointer ptr, size_type size)=0
virtual void construct(pointer ptr, size_type n, value_type const &initial_value)=0
virtual void construct(pointer ptr, size_type n, const_pointer src)=0
virtual void construct(pointer ptr, size_type n)=0
typename std::allocator< T2 >::value_type value_type
Definition Allocator.h:204
virtual void destroy(pointer ptr, size_type n)=0
static constexpr ArrayInitPolicy NO_INIT
Don't initialize elements in the array.
Definition Allocator.h:68
static constexpr ArrayInitPolicy INIT
Initialize all elements in the array with the default value.
Definition Allocator.h:70
casacore_allocator< TOther > other
Definition Allocator.h:91
void deallocate(pointer ptr, size_type)
Definition Allocator.h:114
typename Super::value_type value_type
Definition Allocator.h:85
casacore_allocator() noexcept=default
std11_allocator< T > Super
Definition Allocator.h:78
~casacore_allocator() noexcept=default
typename Super::size_type size_type
Definition Allocator.h:79
static constexpr size_t alignment
Definition Allocator.h:87
pointer allocate(size_type elements, const void *=0)
Definition Allocator.h:102
typename Super::difference_type difference_type
Definition Allocator.h:80
new_del_allocator< TOther > other
Definition Allocator.h:142
typename Super::size_type size_type
Definition Allocator.h:132
void construct(U *ptr, U &value)
Definition Allocator.h:168
pointer allocate(size_type elements, const void *=0)
Definition Allocator.h:153
void construct(U *, Args &&...)
Definition Allocator.h:162
typename Super::difference_type difference_type
Definition Allocator.h:133
typename Super::value_type value_type
Definition Allocator.h:138
void deallocate(pointer ptr, size_type)
Definition Allocator.h:160
new_del_allocator(const new_del_allocator &other) noexcept
Definition Allocator.h:146
std11_allocator< T > Super
Definition Allocator.h:131
void construct(U *ptr, U const &value)
Definition Allocator.h:172
void construct(U *ptr, U &&value)
Definition Allocator.h:164
new_del_allocator(const new_del_allocator< TOther > &) noexcept
Definition Allocator.h:149