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
12namespace Dune
13{
14
22 template<class T, int Alignment = -1>
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 {
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#if defined(_MSC_VER)
83 pointer ret = static_cast<pointer>(_aligned_malloc(alignment, size));
84#else
85 pointer ret = static_cast<pointer>(std::aligned_alloc(alignment, size));
86#endif
87 if (!ret)
88 throw std::bad_alloc();
89
90 return ret;
91 }
92
93#if defined(_MSC_VER)
94 void deallocate(pointer p, [[maybe_unused]] size_type n)
95 {
96 _aligned_free(p);
97 }
98#endif
99 };
100
101}
102
103#endif // DUNE_ALIGNED_ALLOCATOR_HH
Allocators which guarantee alignment of the memory.
Definition: alignedallocator.hh:23
pointer allocate(size_type n, 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
void deallocate(pointer p, size_type n)
deallocate n objects of type T at address p
Definition: mallocallocator.hh:68
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.111.3 (Dec 21, 23:30, 2024)