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