Dune Core Modules (2.7.1)

alignedallocator.hh
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 #ifndef DUNE_ALIGNED_ALLOCATOR_HH
4 #define DUNE_ALIGNED_ALLOCATOR_HH
5 
6 #include "mallocallocator.hh"
7 #include <cstdlib>
8 
9 #if !(DUNE_HAVE_C_ALIGNED_ALLOC || (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600))
10  #error Need either aligned_alloc() or posix_memalign() to compile AlignedAllocator
11 #endif
12 
13 namespace Dune
14 {
15 
23  template<class T, int Alignment = -1>
24  class AlignedAllocator : public MallocAllocator<T> {
25 
26 #if !DUNE_HAVE_C_ALIGNED_ALLOC
27 
28  /*
29  * posix_memalign() on macOS has pretty draconian restrictions on the
30  * alignments that you may ask for: It has to be
31  *
32  * 1) a power of 2
33  * 2) at least as large as sizeof(void*)
34  *
35  * So here is a little constexpr function that calculates just that
36  * (together with the correct starting value for align fed in further down).
37  */
38  static constexpr int fixAlignment(int align)
39  {
40  return ((Alignment==-1) ? std::alignment_of<T>::value : Alignment) > align
41  ? fixAlignment(align << 1) : align;
42  }
43 
44 #else
45 
46  /*
47  * Non-Apple platforms just have to check whether an explicit alignment was
48  * restricted or fall back to the default alignment of T.
49  */
50  static constexpr int fixAlignment(int align)
51  {
52  return (Alignment==-1) ? std::alignment_of<T>::value : Alignment;
53  }
54 
55 #endif
56 
57  public:
58  using pointer = typename MallocAllocator<T>::pointer;
59  using size_type = typename MallocAllocator<T>::size_type;
60  template <class U> struct rebind {
61  typedef AlignedAllocator<U,Alignment> other;
62  };
63 
64  static constexpr int alignment = fixAlignment(sizeof(void*));
65 
67  pointer allocate(size_type n, const void* hint = 0)
68  {
69 
71  if (n > this->max_size())
72  throw std::bad_alloc();
73 
74 #if !DUNE_HAVE_C_ALIGNED_ALLOC
75  /*
76  * Apple's standard library doesn't have aligned_alloc() - C11 is still something
77  * from the future in Cupertino. Luckily, they got around to finally implementing
78  * posix_memalign(), so let's use that instead.
79  */
80  void* ret = nullptr;
81  if (posix_memalign(&ret, alignment, n * sizeof(T)) != 0)
82  throw std::bad_alloc();
83 
84  return static_cast<pointer>(ret);
85 #else
86  /*
87  * Everybody else gets the standard treatment.
88  */
89  pointer ret = static_cast<pointer>(aligned_alloc(alignment, n * sizeof(T)));
90  if (!ret)
91  throw std::bad_alloc();
92 
93  return ret;
94 #endif
95  }
96  };
97 
98 }
99 
100 #endif // DUNE_ALIGNED_ALLOCATOR_HH
Allocators which guarantee alignment of the memory.
Definition: alignedallocator.hh:24
pointer allocate(size_type n, const void *hint=0)
allocate n objects of type T
Definition: alignedallocator.hh:67
Allocators implementation which simply calls malloc/free.
Definition: mallocallocator.hh:23
size_type max_size() const noexcept
max size for allocate
Definition: mallocallocator.hh:75
#define DUNE_UNUSED_PARAMETER(parm)
A macro to mark intentionally unused function parameters with.
Definition: unused.hh:25
Allocators that use malloc/free.
Dune namespace.
Definition: alignedallocator.hh:14
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 8, 22:30, 2024)