casacore
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 
36 #include <memory>
37 #include <typeinfo>
38 
39 #include <cstdlib>
40 namespace casacore { //# NAMESPACE CASACORE - BEGIN
41 
42 #if __cplusplus < 201103L && ! defined(noexcept)
43 # define noexcept throw()
44 # define CASA_UNDEF_noexcept
45 #endif
46 
47 #ifndef CASA_DEFAULT_ALIGNMENT
48 # define CASA_DEFAULT_ALIGNMENT (32UL) // AVX/AVX2 alignment
49 #endif
50 
51 // <summary>
52 // A global enum used by some Array/Block constructors.
53 // </summary>
54 // <synopsis>
55 // ArrayInitPolicy is used in functions where an array is allocated/resized.
56 // </synopsis>
58 public:
59  // Don't initialize elements in the array. (The array will be explicitly filled with values other than the default value.)
60  static ArrayInitPolicy const NO_INIT;
61  // Initialize all elements in the array with the default value.
62  static ArrayInitPolicy const INIT;
64  return init == other.init;
65  }
67  return init != other.init;
68  }
69 private:
71  explicit ArrayInitPolicy(bool v): init(v) {}
72 };
73 
74 #if __cplusplus < 201103L
75 template<typename T>
76 struct std11_allocator: public std::allocator<T> {
77  typedef std::allocator<T> Super;
78  typedef typename Super::size_type size_type;
79  typedef typename Super::difference_type difference_type;
80  typedef typename Super::pointer pointer;
81  typedef typename Super::const_pointer const_pointer;
82  typedef typename Super::reference reference;
83  typedef typename Super::const_reference const_reference;
84  typedef typename Super::value_type value_type;
85 
86  template<typename TOther>
87  struct rebind {
89  };
90  void construct(pointer ptr) {
91  ::new(static_cast<void *>(ptr)) T();
92  }
93  void construct(pointer ptr, const_reference val) {
94  Super::construct(ptr, val);
95  }
96 };
97 
98 template<typename T>
99 inline bool operator==(const std11_allocator<T>&,
100  const std11_allocator<T>&) {
101  return true;
102 }
103 
104 template<typename T>
105 inline bool operator!=(const std11_allocator<T>&,
106  const std11_allocator<T>&) {
107  return false;
108 }
109 
110 #else
111 template<typename T>
112 using std11_allocator = std::allocator<T>;
113 #endif
114 
115 template<typename T, size_t ALIGNMENT = CASA_DEFAULT_ALIGNMENT>
118  typedef typename Super::size_type size_type;
119  typedef typename Super::difference_type difference_type;
120  typedef typename Super::pointer pointer;
121  typedef typename Super::const_pointer const_pointer;
122  typedef typename Super::reference reference;
123  typedef typename Super::const_reference const_reference;
124  typedef typename Super::value_type value_type;
125 #if __cplusplus < 201103L
126  enum {alignment = ALIGNMENT};
127 #else
128  static constexpr size_t alignment = ALIGNMENT;
129 #endif
130 
131  template<typename TOther>
132  struct rebind {
134  };
135  casacore_allocator() throw () {
136  }
137 
139  :Super(other) {
140  }
141 
142  template<typename TOther>
144  }
145 
147  }
148 
149  pointer allocate(size_type elements, const void* = 0) {
150  if (elements > this->max_size()) {
151  throw std::bad_alloc();
152  }
153  void *memptr = 0;
154  int result = posix_memalign(&memptr, ALIGNMENT, sizeof(T) * elements);
155  if (result != 0) {
156  throw std::bad_alloc();
157  }
158  return static_cast<pointer>(memptr);
159  }
160 
161  void deallocate(pointer ptr, size_type) {
162  free(ptr);
163  }
164 };
165 
166 template<typename T, size_t ALIGNMENT>
169  return true;
170 }
171 
172 template<typename T, size_t ALIGNMENT>
175  return false;
176 }
177 
178 template<typename T>
181  typedef typename Super::size_type size_type;
182  typedef typename Super::difference_type difference_type;
183  typedef typename Super::pointer pointer;
184  typedef typename Super::const_pointer const_pointer;
185  typedef typename Super::reference reference;
186  typedef typename Super::const_reference const_reference;
187  typedef typename Super::value_type value_type;
188 
189  template<typename TOther>
190  struct rebind {
192  };
194  }
195 
197  :Super(other) {
198  }
199 
200  template<typename TOther>
202  }
203 
205  }
206 
207  pointer allocate(size_type elements, const void* = 0) {
208  if (elements > this->max_size()) {
209  throw std::bad_alloc();
210  }
211  return new T[elements];
212  }
213 
214  void deallocate(pointer ptr, size_type) {
215  delete[] ptr;
216  }
217 #if __cplusplus < 201103L
218  void construct(pointer ptr, const_reference value) {
219  *ptr = value; // because *ptr was already contructed by new[].
220  }
221  void construct(pointer) {} // do nothing because new T[] does
222 #else
223  template<typename U, typename... Args>
224  void construct(U *, Args&&... ) {} // do nothing because new T[] does
225  template<typename U>
226  void construct(U *ptr, U &&value) {
227  *ptr = value; // because *ptr was already contructed by new[].
228  }
229  template<typename U>
230  void construct(U *ptr, U &value) {
231  *ptr = value; // because *ptr was already contructed by new[].
232  }
233  template<typename U>
234  void construct(U *ptr, U const &value) {
235  *ptr = value; // because *ptr was already contructed by new[].
236  }
237 #endif
238 
239  template<typename U>
240  void destroy(U *) {} // do nothing because delete[] will do.
241 };
242 
243 template<typename T>
244 inline bool operator==(const new_del_allocator<T>&,
245  const new_del_allocator<T>&) {
246  return true;
247 }
248 
249 template<typename T>
250 inline bool operator!=(const new_del_allocator<T>&,
251  const new_del_allocator<T>&) {
252  return false;
253 }
254 
255 template<typename T> class Array;
256 template<typename T> class Block;
257 
259  template<typename T> friend class AbstractAllocator;
260  template<typename T, typename Sub> friend class BaseAllocator;
261  template<typename T> friend class Array;
262  template<typename T> friend class Block;
263 
264  template<typename T2>
265  struct BulkAllocator {
266  typedef typename std::allocator<T2>::size_type size_type;
267  typedef typename std::allocator<T2>::pointer pointer;
268  typedef typename std::allocator<T2>::const_pointer const_pointer;
269  typedef typename std::allocator<T2>::value_type value_type;
270 
271  virtual pointer allocate(size_type elements, const void*ptr = 0) = 0;
272  virtual void deallocate(pointer ptr, size_type size) = 0;
273 
274  virtual void construct(pointer ptr, size_type n, const_pointer src) = 0;
275  virtual void construct(pointer ptr, size_type n, value_type const &initial_value) = 0;
276  virtual void construct(pointer ptr, size_type n) = 0;
277  virtual void destroy(pointer ptr, size_type n) = 0;
278  virtual std::type_info const &allocator_typeid() const = 0;
279  virtual ~BulkAllocator() {}
280  };
281 
282  template<typename Allocator>
283  struct BulkAllocatorImpl: public BulkAllocator<typename Allocator::value_type> {
284  typedef typename Allocator::size_type size_type;
285  typedef typename Allocator::pointer pointer;
286  typedef typename Allocator::const_pointer const_pointer;
287  typedef typename Allocator::value_type value_type;
288  virtual pointer allocate(size_type elements, const void *ptr = 0) {
289  return allocator.allocate(elements, ptr);
290  }
291  virtual void deallocate(pointer ptr, size_type size) {
292  allocator.deallocate(ptr, size);
293  }
294 
295  virtual void construct(pointer ptr, size_type n, const_pointer src) {
296  size_type i = 0;
297  try {
298  for (i = 0; i < n; ++i) {
299  allocator.construct(&ptr[i], src[i]);
300  }
301  } catch (...) {
302  destroy(ptr, i); // rollback constructions
303  throw;
304  }
305  }
306  virtual void construct(pointer ptr, size_type n,
307  value_type const &initial_value) {
308  size_type i = 0;
309  try {
310  for (i = 0; i < n; ++i) {
311  allocator.construct(&ptr[i], initial_value);
312  }
313  } catch (...) {
314  destroy(ptr, i); // rollback constructions
315  throw;
316  }
317  }
318  virtual void construct(pointer ptr, size_type n) {
319  size_type i = 0;
320  try {
321  for (i = 0; i < n; ++i) {
322  allocator.construct(&ptr[i]);
323  }
324  } catch (...) {
325  destroy(ptr, i); // rollback constructions
326  throw;
327  }
328  }
329  virtual void destroy(pointer ptr, size_type n) {
330  for (size_type i = n; i > 0;) {
331  --i;
332  try {
333  allocator.destroy(&ptr[i]);
334  } catch (...) {
335  // Destructor should not raise any exception.
336  }
337  }
338  }
339  virtual std::type_info const &allocator_typeid() const {
340  return typeid(Allocator);
341  }
342  virtual ~BulkAllocatorImpl() {}
343 
344  private:
345  static Allocator allocator;
346  };
347 
348  template<typename Allocator>
350  return get_allocator_raw<Allocator>();
351  }
352  template<typename Allocator>
355  get_allocator_raw<Allocator>();
356  }
358  };
359  template<typename Allocator>
361  static union {
362  void *dummy;
363  char alloc_obj[sizeof(BulkAllocatorImpl<Allocator> )];
364  } u;
365  static BulkAllocatorImpl<Allocator> *ptr = 0;
366  // Probably this method is called from BulkAllocatorInitializer<Allocator> first
367  // while static initialization
368  // and other threads are not started yet.
369  if (ptr == 0) {
370  // Use construct below to avoid https://gcc.gnu.org/bugzilla/show_bug.cgi?id=42032
371  ::new (reinterpret_cast<BulkAllocatorImpl<Allocator>*>(u.alloc_obj)) BulkAllocatorImpl<Allocator>(); // this instance will never be destructed.
372  // ::new (u.alloc_obj) BulkAllocatorImpl<Allocator>(); // this instance will never be destructed.
373  ptr = reinterpret_cast<BulkAllocatorImpl<Allocator> *>(u.alloc_obj);
374  }
375  return ptr;
376  }
377 
378  // <summary>Allocator specifier</summary>
379  // <synopsis>
380  // This class is just used to avoid ambiguity between overloaded functions.
381  // </synopsis>
382  template<typename T>
383  struct AllocSpec {
385  explicit AllocSpec(BulkAllocator<T> *alloc) : allocator(alloc) {}
386  };
387 };
388 
389 template<typename Allocator>
391 
392 template<typename Allocator>
394 
395 template<typename T>
397 public:
398  typedef T value_type;
399  virtual ~AbstractAllocator(){}
400 protected:
402  friend class Array<T>;
403  friend class Block<T>;
404 
405  virtual Allocator_private::BulkAllocator<T> *getAllocator() const = 0;
406 };
407 
408 template<typename T, typename Sub>
410 public:
411  typedef T value_type;
412  typedef Sub facade_type;
413  virtual ~BaseAllocator() {}
414 protected:
416 
418  return Allocator_private::get_allocator<typename facade_type::type>();
419  }
420 };
421 
422 // An allocator behaves like operator new[]/delete[].
423 // Because it is impossible to decouple construction/destruction from allocation/deallocation with this allocator,
424 // it is discouraged to use this allocator.
425 // Use <src>DefaultAllocator<T></src> or <src>AlignedAllocator<T, ALIGNMENT></src> as possible.
426 // This allocator is provided only for compatibility for calling
427 // <src>Array::takeStorage(), Block::replaceStorage(), Block(size_t, T *&, Bool)</src> etc.
428 // with a storage allocated by operator new[].
429 template<typename T>
430 class NewDelAllocator: public BaseAllocator<T, NewDelAllocator<T> > {
431 public:
433  // an instance of this allocator.
435 protected:
437 };
438 template<typename T>
440 
441 // An allocator which allocates aligned memory.
442 template<typename T, size_t ALIGNMENT = CASA_DEFAULT_ALIGNMENT>
443 class AlignedAllocator: public BaseAllocator<T, AlignedAllocator<T, ALIGNMENT> > {
444 public:
446  // an instance of this allocator.
448 protected:
450 };
451 template<typename T, size_t ALIGNMENT>
453 
454 // An aligned allocator with the default alignment.
455 template<typename T>
457 public:
458  typedef typename AlignedAllocator<T>::type type;
459  // an instance of this allocator.
461 protected:
463 };
464 template<typename T>
466 
467 // <summary>Allocator specifier</summary>
468 // <synopsis>
469 // This class is just used to avoid ambiguity between overloaded functions.
470 // </synopsis>
471 template<typename T>
472 struct AllocSpec {
473  typedef T type;
474  static AllocSpec<T> const value;
475 };
476 template<typename T>
478 
479 #if defined(CASA_UNDEF_noexcept)
480 # undef noexcept
481 # undef CASA_UNDEF_noexcept
482 #endif
483 
484 } //# NAMESPACE CASACORE - END
485 
486 #endif /* CASA_CONTAINERS_ALLOCATOR_H_ */
std::allocator< T2 >::pointer pointer
Definition: Allocator.h:267
Super::const_pointer const_pointer
Definition: Allocator.h:81
AlignedAllocator< T >::type type
Definition: Allocator.h:458
std::allocator< T2 >::const_pointer const_pointer
Definition: Allocator.h:268
virtual void destroy(pointer ptr, size_type n)
Definition: Allocator.h:329
Super::const_reference const_reference
Definition: Allocator.h:186
An allocator which allocates aligned memory.
Definition: Allocator.h:443
Super::const_pointer const_pointer
Definition: Allocator.h:184
static NewDelAllocator< T > value
an instance of this allocator.
Definition: Allocator.h:434
static ArrayInitPolicy const NO_INIT
Don&#39;t initialize elements in the array.
Definition: Allocator.h:60
#define noexcept
Definition: Allocator.h:43
std::allocator< T2 >::size_type size_type
Definition: Allocator.h:266
An aligned allocator with the default alignment.
Definition: Allocator.h:456
void deallocate(pointer ptr, size_type)
Definition: Allocator.h:214
virtual std::type_info const & allocator_typeid() const
Definition: Allocator.h:339
virtual Allocator_private::BulkAllocator< T > * getAllocator() const
Definition: Allocator.h:417
virtual void construct(pointer ptr, size_type n, const_pointer src)
Definition: Allocator.h:295
static AllocSpec< T > const value
Definition: Allocator.h:474
Super::difference_type difference_type
Definition: Allocator.h:119
new_del_allocator< TOther > other
Definition: Allocator.h:191
pointer allocate(size_type elements, const void *=0)
Definition: Allocator.h:149
A global enum used by some Array/Block constructors.
Definition: Allocator.h:57
static AlignedAllocator< T, ALIGNMENT > value
an instance of this allocator.
Definition: Allocator.h:447
Super::size_type size_type
Definition: Allocator.h:118
static DefaultAllocator< T > value
an instance of this allocator.
Definition: Allocator.h:460
std11_allocator< TOther > other
Definition: Allocator.h:88
new_del_allocator< T > type
Definition: Allocator.h:432
casacore_allocator< TOther > other
Definition: Allocator.h:133
Super::value_type value_type
Definition: Allocator.h:84
Super::pointer pointer
Definition: Allocator.h:183
void construct(pointer ptr, const_reference value)
Definition: Allocator.h:218
std::allocator< T > Super
Definition: Allocator.h:77
new_del_allocator(const new_del_allocator &other) noexcept
Definition: Allocator.h:196
Super::value_type value_type
Definition: Allocator.h:124
void construct(pointer ptr, const_reference val)
Definition: Allocator.h:93
Super::pointer pointer
Definition: Allocator.h:80
casacore_allocator< T, ALIGNMENT > type
Definition: Allocator.h:445
new_del_allocator(const new_del_allocator< TOther > &) noexcept
Definition: Allocator.h:201
Super::const_pointer const_pointer
Definition: Allocator.h:121
virtual void construct(pointer ptr, size_type n, value_type const &initial_value)
Definition: Allocator.h:306
static ArrayInitPolicy const INIT
Initialize all elements in the array with the default value.
Definition: Allocator.h:62
virtual void deallocate(pointer ptr, size_type size)
Definition: Allocator.h:291
Super::const_reference const_reference
Definition: Allocator.h:123
void deallocate(pointer ptr, size_type)
Definition: Allocator.h:161
bool Bool
Define the standard types used by Casacore.
Definition: aipstype.h:42
static BulkAllocatorImpl< Allocator > * get_allocator_raw()
Definition: Allocator.h:360
void construct(pointer ptr)
Definition: Allocator.h:90
virtual pointer allocate(size_type elements, const void *ptr=0)
Definition: Allocator.h:288
virtual void construct(pointer ptr, size_type n)
Definition: Allocator.h:318
template <class T, class U> class vector;
Definition: Array.h:169
std::allocator< T2 >::value_type value_type
Definition: Allocator.h:269
Bool operator!=(ArrayInitPolicy const &other)
Definition: Allocator.h:66
pointer allocate(size_type elements, const void *=0)
Definition: Allocator.h:207
simple 1-D array
Definition: ArrayIO.h:47
free(pool)
Bool operator==(ArrayInitPolicy const &other)
Definition: Allocator.h:63
AllocSpec(BulkAllocator< T > *alloc)
Definition: Allocator.h:385
Super::value_type value_type
Definition: Allocator.h:187
Allocator specifier.
Definition: Allocator.h:472
casacore_allocator(const casacore_allocator &other) noexcept
Definition: Allocator.h:138
Super::reference reference
Definition: Allocator.h:185
static BulkAllocator< typename Allocator::value_type > * get_allocator()
Definition: Allocator.h:349
An allocator behaves like operator new[]/delete[].
Definition: Allocator.h:430
Super::reference reference
Definition: Allocator.h:122
casacore_allocator(const casacore_allocator< TOther > &) noexcept
Definition: Allocator.h:143
std11_allocator< T > Super
Definition: Allocator.h:117
Super::difference_type difference_type
Definition: Allocator.h:79
Super::size_type size_type
Definition: Allocator.h:181
Super::size_type size_type
Definition: Allocator.h:78
Super::reference reference
Definition: Allocator.h:82
this file contains all the compiler specific defines
Definition: mainpage.dox:28
Super::difference_type difference_type
Definition: Allocator.h:182
std11_allocator< T > Super
Definition: Allocator.h:180
LatticeExprNode value(const LatticeExprNode &expr)
This function returns the value of the expression without a mask.
static BulkAllocatorInitializer< Allocator > instance
Definition: Allocator.h:357
Super::const_reference const_reference
Definition: Allocator.h:83
virtual ~BaseAllocator()
Definition: Allocator.h:413