Dune Core Modules (unstable)

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 // SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4 // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
5 #ifndef DUNE_ALIGNED_ALLOCATOR_HH
6 #define DUNE_ALIGNED_ALLOCATOR_HH
7 
8 #include "mallocallocator.hh"
9 #include <cstdlib>
10 #include <type_traits>
11 
12 namespace Dune
13 {
14 
22  template<class T, int Alignment = -1>
23  class AlignedAllocator : public MallocAllocator<T> {
24 
25 #if __APPLE__
26 
27  /*
28  * macOS has pretty draconian restrictions on the
29  * alignments that you may ask for: It has to be
30  *
31  * 1) a power of 2
32  * 2) at least as large as sizeof(void*)
33  *
34  * So here is a little constexpr function that calculates just that
35  * (together with the correct starting value for align fed in further down).
36  */
37  static constexpr int fixAlignment(int align)
38  {
39  return ((Alignment==-1) ? std::alignment_of<T>::value : Alignment) > align
40  ? fixAlignment(align << 1) : align;
41  }
42 
43 #else
44 
45  /*
46  * Non-Apple platforms we just have to check whether an explicit alignment was
47  * restricted or fall back to the default alignment of T.
48  */
49  static constexpr int fixAlignment(int align)
50  {
51  return (Alignment==-1) ? std::alignment_of<T>::value : Alignment;
52  }
53 
54 #endif
55 
56  public:
57  using pointer = typename MallocAllocator<T>::pointer;
58  using size_type = typename MallocAllocator<T>::size_type;
59  template <class U> struct rebind {
60  typedef AlignedAllocator<U,Alignment> other;
61  };
62 
63  static constexpr int alignment = fixAlignment(sizeof(void*));
64 
66  pointer allocate(size_type n, [[maybe_unused]] const void* hint = 0)
67  {
68  if (n > this->max_size())
69  throw std::bad_alloc();
70 
71 #if __APPLE__
72  // Apple is also restrictive regarding the allocation size.
73  // size must be at least the alignment size.
74  size_type size = n * sizeof(T) >= alignment ? n * sizeof(T) : alignment;
75 #else
76  size_type size = n * sizeof(T);
77 #endif
78 
79  /*
80  * Everybody else gets the standard treatment.
81  */
82  pointer ret = static_cast<pointer>(std::aligned_alloc(alignment, size));
83  if (!ret)
84  throw std::bad_alloc();
85 
86  return ret;
87  }
88  };
89 
90 }
91 
92 #endif // DUNE_ALIGNED_ALLOCATOR_HH
Allocators which guarantee alignment of the memory.
Definition: alignedallocator.hh:23
pointer allocate(size_type n, [[maybe_unused]] const void *hint=0)
allocate n objects of type T
Definition: alignedallocator.hh:66
Allocators implementation which simply calls malloc/free.
Definition: mallocallocator.hh:24
size_type max_size() const noexcept
max size for allocate
Definition: mallocallocator.hh:74
Allocators that use malloc/free.
Dune namespace.
Definition: alignedallocator.hh:13
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (Apr 26, 22:29, 2024)