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 <cstdlib>
36#include <memory>
37#include <new>
38#include <typeinfo>
39#include <type_traits>
40
41namespace casacore { //# NAMESPACE CASACORE - BEGIN
42
43#ifndef CASA_DEFAULT_ALIGNMENT
44# define CASA_DEFAULT_ALIGNMENT (32UL) // AVX/AVX2 alignment
45#endif
46
47// <summary>
48// A global enum used by some Array/Block constructors.
49// </summary>
50// <synopsis>
51// ArrayInitPolicy is used in functions where an array is allocated/resized.
52// </synopsis>
54public:
56 return init == other.init;
57 }
59 return init != other.init;
60 }
61private:
63 explicit constexpr ArrayInitPolicy(bool v): init(v) {}
64 friend struct ArrayInitPolicies;
65};
66
68 // Don't initialize elements in the array. (The array will be explicitly filled with values other than the default value.)
69 static constexpr ArrayInitPolicy NO_INIT = ArrayInitPolicy(false);
70 // Initialize all elements in the array with the default value.
71 static constexpr ArrayInitPolicy INIT = ArrayInitPolicy(true);
72};
73
74template<typename T>
75using std11_allocator = std::allocator<T>;
76
77
78template<typename T, size_t ALIGNMENT = CASA_DEFAULT_ALIGNMENT>
81 using size_type = typename Super::size_type;
82 using difference_type = typename Super::difference_type;
83 using pointer = T*;
84 using const_pointer = const T*;
85 using reference = T&;
86 using const_reference = const T&;
87 using value_type = typename Super::value_type;
88
89 static constexpr size_t alignment = ALIGNMENT;
90
91 template<typename TOther>
95 casacore_allocator() noexcept = default;
96
97 casacore_allocator(const casacore_allocator&other) noexcept = default;
98
99 template<typename TOther>
100 casacore_allocator(const casacore_allocator<TOther>&) noexcept {}
101
102 ~casacore_allocator() noexcept = default;
103
104 pointer allocate(size_type elements, const void* = 0) {
105 if (elements > std::allocator_traits<casacore_allocator>::max_size(*this)) {
106 throw std::bad_alloc();
107 }
108 void *memptr = 0;
109 int result = posix_memalign(&memptr, ALIGNMENT, sizeof(T) * elements);
110 if (result != 0) {
111 throw std::bad_alloc();
112 }
113 return static_cast<pointer>(memptr);
114 }
115
117 free(ptr);
118 }
119};
120
121template<typename T, size_t ALIGNMENT>
124 return true;
125}
126
127template<typename T, size_t ALIGNMENT>
130 return false;
131}
132
133template<typename T>
136 using size_type = typename Super::size_type;
137 using difference_type = typename Super::difference_type;
138 using pointer = T*;
139 using const_pointer = const T*;
140 using reference = T&;
141 using const_reference = const T&;
142 using value_type = typename Super::value_type;
143
144 template<typename TOther>
148 new_del_allocator() noexcept {
149 }
150
152 :Super(other) {
153 }
154
155 template<typename TOther>
158
160 }
161
162 pointer allocate(size_type elements, const void* = 0) {
163 if (elements > std::allocator_traits<new_del_allocator>::max_size(*this)) {
164 throw std::bad_alloc();
165 }
166 return new T[elements];
167 }
168
170 delete[] ptr;
171 }
172 template<typename U, typename... Args>
173 void construct(U *, Args&&... ) {} // do nothing because new T[] does
174 template<typename U>
175 void construct(U *ptr, U &&value) {
176 *ptr = value; // because *ptr was already contructed by new[].
177 }
178 template<typename U>
179 void construct(U *ptr, U &value) {
180 *ptr = value; // because *ptr was already contructed by new[].
181 }
182 template<typename U>
183 void construct(U *ptr, U const &value) {
184 *ptr = value; // because *ptr was already contructed by new[].
185 }
186
187 template<typename U>
188 void destroy(U *) {} // do nothing because delete[] will do.
189};
190
191template<typename T>
193 const new_del_allocator<T>&) {
194 return true;
195}
196
197template<typename T>
199 const new_del_allocator<T>&) {
200 return false;
201}
202
203template<typename T> class Block;
204
206 template<typename T> friend class AbstractAllocator;
207 template<typename T, typename Sub> friend class BaseAllocator;
208 template<typename T> friend class Block;
209
210 template<typename T2>
212 using size_type = typename std::allocator<T2>::size_type;
213 using value_type = typename std::allocator<T2>::value_type;
214 using pointer = T2*;
215 using const_pointer = const T2*;
216
217 virtual pointer allocate(size_type elements, const void*ptr = 0) = 0;
218 virtual void deallocate(pointer ptr, size_type size) = 0;
219
220 virtual void construct(pointer ptr, size_type n, const_pointer src) = 0;
221 virtual void construct(pointer ptr, size_type n, value_type const &initial_value) = 0;
222 virtual void construct(pointer ptr, size_type n) = 0;
223 virtual void destroy(pointer ptr, size_type n) = 0;
224 virtual std::type_info const &allocator_typeid() const = 0;
225 virtual ~BulkAllocator() {}
226 };
227
228 template<typename Allocator>
229 struct BulkAllocatorImpl: public BulkAllocator<typename Allocator::value_type> {
230 typedef typename Allocator::size_type size_type;
231 typedef typename Allocator::pointer pointer;
232 typedef typename Allocator::const_pointer const_pointer;
233 typedef typename Allocator::value_type value_type;
234 virtual pointer allocate(size_type elements, const void *ptr = 0) override {
235 return allocator.allocate(elements, ptr);
236 }
237 virtual void deallocate(pointer ptr, size_type size) override {
238 allocator.deallocate(ptr, size);
239 }
240
241 virtual void construct(pointer ptr, size_type n, const_pointer src) override {
242 size_type i = 0;
243 try {
244 for (i = 0; i < n; ++i) {
245 std::allocator_traits<Allocator>::construct(allocator, &ptr[i], src[i]);
246 }
247 } catch (...) {
248 destroy(ptr, i); // rollback constructions
249 throw;
250 }
251 }
252 virtual void construct(pointer ptr, size_type n,
253 value_type const &initial_value) override {
254 size_type i = 0;
255 try {
256 for (i = 0; i < n; ++i) {
257 std::allocator_traits<Allocator>::construct(allocator, &ptr[i], initial_value);
258 }
259 } catch (...) {
260 destroy(ptr, i); // rollback constructions
261 throw;
262 }
263 }
264 virtual void construct(pointer ptr, size_type n) override {
265 size_type i = 0;
266 try {
267 for (i = 0; i < n; ++i) {
268 std::allocator_traits<Allocator>::construct(allocator, &ptr[i]);
269 }
270 } catch (...) {
271 destroy(ptr, i); // rollback constructions
272 throw;
273 }
274 }
275 virtual void destroy(pointer ptr, size_type n) override {
276 for (size_type i = n; i > 0;) {
277 --i;
278 try {
279 std::allocator_traits<Allocator>::destroy(allocator, &ptr[i]);
280 } catch (...) {
281 // Destructor should not raise any exception.
282 }
283 }
284 }
285 virtual std::type_info const &allocator_typeid() const override {
286 return typeid(Allocator);
287 }
288 virtual ~BulkAllocatorImpl() override {}
289
290 private:
291 static Allocator allocator;
292 };
293
294 template<typename Allocator>
298
299 template<typename Allocator>
301 // Because this function gets called from destructors of statically allocated objects that get destructed
302 // after the program finishes, the allocator is constructed in a static storage space and is never
303 // destructed.
304 alignas(BulkAllocatorImpl<Allocator>) static std::byte storage[sizeof(BulkAllocatorImpl<Allocator>)];
305 static BulkAllocatorImpl<Allocator>* ptr =
306 new (reinterpret_cast<BulkAllocatorImpl<Allocator>*>(&storage)) BulkAllocatorImpl<Allocator>();
307 return ptr;
308 }
309
310 // <summary>Allocator specifier</summary>
311 // <synopsis>
312 // This class is just used to avoid ambiguity between overloaded functions.
313 // </synopsis>
314 template<typename T>
315 struct AllocSpec {
317 explicit AllocSpec(BulkAllocator<T> *alloc) : allocator(alloc) {}
318 };
319};
320
321template<typename Allocator>
323
324template<typename T>
326public:
327 typedef T value_type;
329protected:
331 friend class Array<T>;
332 friend class Block<T>;
333
335};
336
337template<typename T, typename Sub>
339public:
340 typedef T value_type;
341 typedef Sub facade_type;
342 virtual ~BaseAllocator() {}
343protected:
345
349};
350
351// An allocator behaves like operator new[]/delete[].
352// Because it is impossible to decouple construction/destruction from allocation/deallocation with this allocator,
353// it is discouraged to use this allocator.
354// Use <src>DefaultAllocator<T></src> or <src>AlignedAllocator<T, ALIGNMENT></src> as possible.
355// This allocator is provided only for compatibility for calling
356// <src>Array::takeStorage(), Block::replaceStorage(), Block(size_t, T *&, Bool)</src> etc.
357// with a storage allocated by operator new[].
358template<typename T>
359class NewDelAllocator: public BaseAllocator<T, NewDelAllocator<T> > {
360public:
362 // an instance of this allocator.
364protected:
366};
367template<typename T>
369
370// An allocator which allocates aligned memory.
371template<typename T, size_t ALIGNMENT = CASA_DEFAULT_ALIGNMENT>
372class AlignedAllocator: public BaseAllocator<T, AlignedAllocator<T, ALIGNMENT> > {
373public:
375 // an instance of this allocator.
377protected:
379};
380template<typename T, size_t ALIGNMENT>
382
383// An aligned allocator with the default alignment.
384template<typename T>
386public:
388 // an instance of this allocator.
390protected:
392};
393template<typename T>
395
396// <summary>Allocator specifier</summary>
397// <synopsis>
398// This class is just used to avoid ambiguity between overloaded functions.
399// </synopsis>
400template<typename T>
401struct AllocSpec {
402 typedef T type;
403 static AllocSpec<T> const value;
404};
405template<typename T>
407
408
409} //# NAMESPACE CASACORE - END
410
411#endif /* CASA_CONTAINERS_ALLOCATOR_H_ */
virtual Allocator_private::BulkAllocator< T > * getAllocator() const =0
An allocator which allocates aligned memory.
Definition Allocator.h:372
static AlignedAllocator< T, CASA_DEFAULT_ALIGNMENT > value
Definition Allocator.h:376
casacore_allocator< T, ALIGNMENT > type
Definition Allocator.h:374
static BulkAllocator< typename Allocator::value_type > * get_allocator()
Definition Allocator.h:295
static BulkAllocatorImpl< Allocator > * get_allocator_raw()
Definition Allocator.h:300
friend class AbstractAllocator
Definition Allocator.h:206
Bool operator==(ArrayInitPolicy const &other)
Definition Allocator.h:55
friend struct ArrayInitPolicies
Definition Allocator.h:64
constexpr ArrayInitPolicy(bool v)
Definition Allocator.h:63
Bool operator!=(ArrayInitPolicy const &other)
Definition Allocator.h:58
virtual Allocator_private::BulkAllocator< T > * getAllocator() const override
Definition Allocator.h:346
simple 1-D array
Definition Block.h:198
An aligned allocator with the default alignment.
Definition Allocator.h:385
static DefaultAllocator< T > value
an instance of this allocator.
Definition Allocator.h:389
AlignedAllocator< T >::type type
Definition Allocator.h:387
An allocator behaves like operator new[]/delete[].
Definition Allocator.h:359
new_del_allocator< T > type
Definition Allocator.h:361
static NewDelAllocator< T > value
an instance of this allocator.
Definition Allocator.h:363
free(pool)
this file contains all the compiler specific defines
Definition mainpage.dox:28
bool operator==(const casacore_allocator< T, ALIGNMENT > &, const casacore_allocator< T, ALIGNMENT > &)
Definition Allocator.h:122
bool operator!=(const casacore_allocator< T, ALIGNMENT > &, const casacore_allocator< T, ALIGNMENT > &)
Definition Allocator.h:128
bool Bool
Define the standard types used by Casacore.
Definition aipstype.h:40
uInt size() const
NewDelAllocator< T > NewDelAllocator< T >::value
Definition Allocator.h:368
std::allocator< T > std11_allocator
Definition Allocator.h:75
Allocator specifier.
Definition Allocator.h:401
static AllocSpec< T > const value
Definition Allocator.h:403
AllocSpec(BulkAllocator< T > *alloc)
Definition Allocator.h:317
virtual void construct(pointer ptr, size_type n, const_pointer src) override
Definition Allocator.h:241
virtual void construct(pointer ptr, size_type n, value_type const &initial_value) override
Definition Allocator.h:252
virtual void construct(pointer ptr, size_type n) override
Definition Allocator.h:264
virtual void deallocate(pointer ptr, size_type size) override
Definition Allocator.h:237
virtual void destroy(pointer ptr, size_type n) override
Definition Allocator.h:275
virtual std::type_info const & allocator_typeid() const override
Definition Allocator.h:285
virtual pointer allocate(size_type elements, const void *ptr=0) override
Definition Allocator.h:234
virtual std::type_info const & allocator_typeid() const =0
typename std::allocator< T2 >::size_type size_type
Definition Allocator.h:212
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:213
virtual void destroy(pointer ptr, size_type n)=0
static constexpr ArrayInitPolicy NO_INIT
Don't initialize elements in the array.
Definition Allocator.h:69
static constexpr ArrayInitPolicy INIT
Initialize all elements in the array with the default value.
Definition Allocator.h:71
casacore_allocator< TOther > other
Definition Allocator.h:93
void deallocate(pointer ptr, size_type)
Definition Allocator.h:116
typename Super::value_type value_type
Definition Allocator.h:87
casacore_allocator() noexcept=default
std11_allocator< T > Super
Definition Allocator.h:80
~casacore_allocator() noexcept=default
typename Super::size_type size_type
Definition Allocator.h:81
static constexpr size_t alignment
Definition Allocator.h:89
pointer allocate(size_type elements, const void *=0)
Definition Allocator.h:104
typename Super::difference_type difference_type
Definition Allocator.h:82
new_del_allocator< TOther > other
Definition Allocator.h:146
typename Super::size_type size_type
Definition Allocator.h:136
void construct(U *ptr, U &value)
Definition Allocator.h:179
pointer allocate(size_type elements, const void *=0)
Definition Allocator.h:162
void construct(U *, Args &&...)
Definition Allocator.h:173
typename Super::difference_type difference_type
Definition Allocator.h:137
typename Super::value_type value_type
Definition Allocator.h:142
void deallocate(pointer ptr, size_type)
Definition Allocator.h:169
new_del_allocator(const new_del_allocator &other) noexcept
Definition Allocator.h:151
std11_allocator< T > Super
Definition Allocator.h:135
void construct(U *ptr, U const &value)
Definition Allocator.h:183
void construct(U *ptr, U &&value)
Definition Allocator.h:175
new_del_allocator(const new_del_allocator< TOther > &) noexcept
Definition Allocator.h:156