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() throw () {
96 }
97
99 :Super(other) {
100 }
101
102 template<typename TOther>
105
107 }
108
109 pointer allocate(size_type elements, const void* = 0) {
110 if (elements > std::allocator_traits<casacore_allocator>::max_size(*this)) {
111 throw std::bad_alloc();
112 }
113 void *memptr = 0;
114 int result = posix_memalign(&memptr, ALIGNMENT, sizeof(T) * elements);
115 if (result != 0) {
116 throw std::bad_alloc();
117 }
118 return static_cast<pointer>(memptr);
119 }
120
122 free(ptr);
123 }
124};
125
126template<typename T, size_t ALIGNMENT>
129 return true;
130}
131
132template<typename T, size_t ALIGNMENT>
135 return false;
136}
137
138template<typename T>
141 using size_type = typename Super::size_type;
142 using difference_type = typename Super::difference_type;
143 using pointer = T*;
144 using const_pointer = const T*;
145 using reference = T&;
146 using const_reference = const T&;
147 using value_type = typename Super::value_type;
148
149 template<typename TOther>
153 new_del_allocator() noexcept {
154 }
155
157 :Super(other) {
158 }
159
160 template<typename TOther>
163
165 }
166
167 pointer allocate(size_type elements, const void* = 0) {
168 if (elements > std::allocator_traits<new_del_allocator>::max_size(*this)) {
169 throw std::bad_alloc();
170 }
171 return new T[elements];
172 }
173
175 delete[] ptr;
176 }
177 template<typename U, typename... Args>
178 void construct(U *, Args&&... ) {} // do nothing because new T[] does
179 template<typename U>
180 void construct(U *ptr, U &&value) {
181 *ptr = value; // because *ptr was already contructed by new[].
182 }
183 template<typename U>
184 void construct(U *ptr, U &value) {
185 *ptr = value; // because *ptr was already contructed by new[].
186 }
187 template<typename U>
188 void construct(U *ptr, U const &value) {
189 *ptr = value; // because *ptr was already contructed by new[].
190 }
191
192 template<typename U>
193 void destroy(U *) {} // do nothing because delete[] will do.
194};
195
196template<typename T>
198 const new_del_allocator<T>&) {
199 return true;
200}
201
202template<typename T>
204 const new_del_allocator<T>&) {
205 return false;
206}
207
208template<typename T> class Block;
209
211 template<typename T> friend class AbstractAllocator;
212 template<typename T, typename Sub> friend class BaseAllocator;
213 template<typename T> friend class Block;
214
215 template<typename T2>
217 using size_type = typename std::allocator<T2>::size_type;
218 using value_type = typename std::allocator<T2>::value_type;
219 using pointer = T2*;
220 using const_pointer = const T2*;
221
222 virtual pointer allocate(size_type elements, const void*ptr = 0) = 0;
223 virtual void deallocate(pointer ptr, size_type size) = 0;
224
225 virtual void construct(pointer ptr, size_type n, const_pointer src) = 0;
226 virtual void construct(pointer ptr, size_type n, value_type const &initial_value) = 0;
227 virtual void construct(pointer ptr, size_type n) = 0;
228 virtual void destroy(pointer ptr, size_type n) = 0;
229 virtual std::type_info const &allocator_typeid() const = 0;
230 virtual ~BulkAllocator() {}
231 };
232
233 template<typename Allocator>
234 struct BulkAllocatorImpl: public BulkAllocator<typename Allocator::value_type> {
235 typedef typename Allocator::size_type size_type;
236 typedef typename Allocator::pointer pointer;
237 typedef typename Allocator::const_pointer const_pointer;
238 typedef typename Allocator::value_type value_type;
239 virtual pointer allocate(size_type elements, const void *ptr = 0) override {
240 return allocator.allocate(elements, ptr);
241 }
242 virtual void deallocate(pointer ptr, size_type size) override {
243 allocator.deallocate(ptr, size);
244 }
245
246 virtual void construct(pointer ptr, size_type n, const_pointer src) override {
247 size_type i = 0;
248 try {
249 for (i = 0; i < n; ++i) {
250 std::allocator_traits<Allocator>::construct(allocator, &ptr[i], src[i]);
251 }
252 } catch (...) {
253 destroy(ptr, i); // rollback constructions
254 throw;
255 }
256 }
257 virtual void construct(pointer ptr, size_type n,
258 value_type const &initial_value) override {
259 size_type i = 0;
260 try {
261 for (i = 0; i < n; ++i) {
262 std::allocator_traits<Allocator>::construct(allocator, &ptr[i], initial_value);
263 }
264 } catch (...) {
265 destroy(ptr, i); // rollback constructions
266 throw;
267 }
268 }
269 virtual void construct(pointer ptr, size_type n) override {
270 size_type i = 0;
271 try {
272 for (i = 0; i < n; ++i) {
273 std::allocator_traits<Allocator>::construct(allocator, &ptr[i]);
274 }
275 } catch (...) {
276 destroy(ptr, i); // rollback constructions
277 throw;
278 }
279 }
280 virtual void destroy(pointer ptr, size_type n) override {
281 for (size_type i = n; i > 0;) {
282 --i;
283 try {
284 std::allocator_traits<Allocator>::destroy(allocator, &ptr[i]);
285 } catch (...) {
286 // Destructor should not raise any exception.
287 }
288 }
289 }
290 virtual std::type_info const &allocator_typeid() const override {
291 return typeid(Allocator);
292 }
293 virtual ~BulkAllocatorImpl() override {}
294
295 private:
296 static Allocator allocator;
297 };
298
299 template<typename Allocator>
301 return get_allocator_raw<Allocator>();
302 }
303
304 template<typename Allocator>
306 // Because this function gets called from destructors of statically allocated objects that get destructed
307 // after the program finishes, the allocator is constructed in a static storage space and is never
308 // destructed.
309 static typename std::aligned_storage<sizeof(BulkAllocatorImpl<Allocator>), alignof(BulkAllocatorImpl<Allocator>)>::type storage;
310 static BulkAllocatorImpl<Allocator>* ptr =
311 new (reinterpret_cast<BulkAllocatorImpl<Allocator>*>(&storage)) BulkAllocatorImpl<Allocator>();
312 return ptr;
313 }
314
315 // <summary>Allocator specifier</summary>
316 // <synopsis>
317 // This class is just used to avoid ambiguity between overloaded functions.
318 // </synopsis>
319 template<typename T>
320 struct AllocSpec {
322 explicit AllocSpec(BulkAllocator<T> *alloc) : allocator(alloc) {}
323 };
324};
325
326template<typename Allocator>
328
329template<typename T>
331public:
332 typedef T value_type;
334protected:
336 friend class Array<T>;
337 friend class Block<T>;
338
340};
341
342template<typename T, typename Sub>
344public:
345 typedef T value_type;
346 typedef Sub facade_type;
347 virtual ~BaseAllocator() {}
348protected:
350
351 virtual typename Allocator_private::BulkAllocator<T> *getAllocator() const override {
352 return Allocator_private::get_allocator<typename facade_type::type>();
353 }
354};
355
356// An allocator behaves like operator new[]/delete[].
357// Because it is impossible to decouple construction/destruction from allocation/deallocation with this allocator,
358// it is discouraged to use this allocator.
359// Use <src>DefaultAllocator<T></src> or <src>AlignedAllocator<T, ALIGNMENT></src> as possible.
360// This allocator is provided only for compatibility for calling
361// <src>Array::takeStorage(), Block::replaceStorage(), Block(size_t, T *&, Bool)</src> etc.
362// with a storage allocated by operator new[].
363template<typename T>
364class NewDelAllocator: public BaseAllocator<T, NewDelAllocator<T> > {
365public:
367 // an instance of this allocator.
369protected:
371};
372template<typename T>
373NewDelAllocator<T> NewDelAllocator<T>::value;
374
375// An allocator which allocates aligned memory.
376template<typename T, size_t ALIGNMENT = CASA_DEFAULT_ALIGNMENT>
377class AlignedAllocator: public BaseAllocator<T, AlignedAllocator<T, ALIGNMENT> > {
378public:
380 // an instance of this allocator.
382protected:
384};
385template<typename T, size_t ALIGNMENT>
386AlignedAllocator<T, ALIGNMENT> AlignedAllocator<T, ALIGNMENT>::value;
387
388// An aligned allocator with the default alignment.
389template<typename T>
391public:
393 // an instance of this allocator.
395protected:
397};
398template<typename T>
399DefaultAllocator<T> DefaultAllocator<T>::value;
400
401// <summary>Allocator specifier</summary>
402// <synopsis>
403// This class is just used to avoid ambiguity between overloaded functions.
404// </synopsis>
405template<typename T>
406struct AllocSpec {
407 typedef T type;
408 static AllocSpec<T> const value;
409};
410template<typename T>
412
413
414} //# NAMESPACE CASACORE - END
415
416#endif /* CASA_CONTAINERS_ALLOCATOR_H_ */
virtual Allocator_private::BulkAllocator< T > * getAllocator() const =0
An allocator which allocates aligned memory.
Definition Allocator.h:377
static AlignedAllocator< T, ALIGNMENT > value
an instance of this allocator.
Definition Allocator.h:381
casacore_allocator< T, ALIGNMENT > type
Definition Allocator.h:379
static BulkAllocator< typename Allocator::value_type > * get_allocator()
Definition Allocator.h:300
static BulkAllocatorImpl< Allocator > * get_allocator_raw()
Definition Allocator.h:305
Bool operator==(ArrayInitPolicy const &other)
Definition Allocator.h:55
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:351
simple 1-D array
Definition Block.h:198
An aligned allocator with the default alignment.
Definition Allocator.h:390
static DefaultAllocator< T > value
an instance of this allocator.
Definition Allocator.h:394
AlignedAllocator< T >::type type
Definition Allocator.h:392
An allocator behaves like operator new[]/delete[].
Definition Allocator.h:364
static NewDelAllocator< T > value
an instance of this allocator.
Definition Allocator.h:368
new_del_allocator< T > type
Definition Allocator.h:366
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:127
bool operator!=(const casacore_allocator< T, ALIGNMENT > &, const casacore_allocator< T, ALIGNMENT > &)
Definition Allocator.h:133
std::allocator< T > std11_allocator
Definition Allocator.h:75
bool Bool
Define the standard types used by Casacore.
Definition aipstype.h:40
LatticeExprNode value(const LatticeExprNode &expr)
This function returns the value of the expression without a mask.
Allocator specifier.
Definition Allocator.h:406
static AllocSpec< T > const value
Definition Allocator.h:408
AllocSpec(BulkAllocator< T > *alloc)
Definition Allocator.h:322
virtual void construct(pointer ptr, size_type n, const_pointer src) override
Definition Allocator.h:246
virtual void construct(pointer ptr, size_type n, value_type const &initial_value) override
Definition Allocator.h:257
virtual void construct(pointer ptr, size_type n) override
Definition Allocator.h:269
virtual void deallocate(pointer ptr, size_type size) override
Definition Allocator.h:242
virtual void destroy(pointer ptr, size_type n) override
Definition Allocator.h:280
virtual std::type_info const & allocator_typeid() const override
Definition Allocator.h:290
virtual pointer allocate(size_type elements, const void *ptr=0) override
Definition Allocator.h:239
virtual std::type_info const & allocator_typeid() const =0
typename std::allocator< T2 >::size_type size_type
Definition Allocator.h:217
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:218
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:121
casacore_allocator(const casacore_allocator< TOther > &) noexcept
Definition Allocator.h:103
typename Super::value_type value_type
Definition Allocator.h:87
std11_allocator< T > Super
Definition Allocator.h:80
typename Super::size_type size_type
Definition Allocator.h:81
casacore_allocator(const casacore_allocator &other) noexcept
Definition Allocator.h:98
static constexpr size_t alignment
Definition Allocator.h:89
pointer allocate(size_type elements, const void *=0)
Definition Allocator.h:109
typename Super::difference_type difference_type
Definition Allocator.h:82
new_del_allocator< TOther > other
Definition Allocator.h:151
typename Super::size_type size_type
Definition Allocator.h:141
void construct(U *ptr, U &value)
Definition Allocator.h:184
pointer allocate(size_type elements, const void *=0)
Definition Allocator.h:167
void construct(U *, Args &&...)
Definition Allocator.h:178
typename Super::difference_type difference_type
Definition Allocator.h:142
typename Super::value_type value_type
Definition Allocator.h:147
void deallocate(pointer ptr, size_type)
Definition Allocator.h:174
new_del_allocator(const new_del_allocator &other) noexcept
Definition Allocator.h:156
std11_allocator< T > Super
Definition Allocator.h:140
void construct(U *ptr, U const &value)
Definition Allocator.h:188
void construct(U *ptr, U &&value)
Definition Allocator.h:180
new_del_allocator(const new_del_allocator< TOther > &) noexcept
Definition Allocator.h:161