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