• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

STEllAR-GROUP / hpx / #882

31 Aug 2023 07:44PM UTC coverage: 41.798% (-44.7%) from 86.546%
#882

push

19442 of 46514 relevant lines covered (41.8%)

126375.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.78
/libs/core/allocator_support/include/hpx/allocator_support/aligned_allocator.hpp
1
//  Copyright (c) 2020 Thomas Heller
2
//  Copyright (c) 2023-2025 Hartmut Kaiser
3
//
4
//  SPDX-License-Identifier: BSL-1.0
5
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
6
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7

8
#pragma once
9

10
#include <hpx/config.hpp>
11
#include <hpx/modules/preprocessor.hpp>
12
#include <hpx/modules/type_support.hpp>
13

14
#include <cstddef>
15
#include <limits>
16
#include <memory>
17
#include <new>
18
#include <type_traits>
19
#include <utility>
20

21
#if defined(HPX_HAVE_JEMALLOC_PREFIX)
22
// this is currently used only for jemalloc and if a special API prefix is
23
// used for its APIs
24
#include <jemalloc/jemalloc.h>
25

26
namespace hpx::util::detail {
27

28
    [[nodiscard]] inline void* __aligned_alloc(
29
        std::size_t alignment, std::size_t size) noexcept
30
    {
31
        return HPX_PP_CAT(HPX_HAVE_JEMALLOC_PREFIX, aligned_alloc)(
32
            alignment, size);
33
    }
34

35
    inline void __aligned_free(void* p, std::size_t) noexcept
36
    {
37
        return HPX_PP_CAT(HPX_HAVE_JEMALLOC_PREFIX, free)(p);
38
    }
39
}    // namespace hpx::util::detail
40

41
#elif defined(HPX_HAVE_CXX17_STD_ALIGNED_ALLOC)
42

43
#include <cstdlib>
44

45
namespace hpx::util::detail {
46

47
    [[nodiscard]] inline void* __aligned_alloc(
48
        std::size_t alignment, std::size_t size) noexcept
49
    {
50
        return std::aligned_alloc(alignment, size);
175,392✔
51
    }
52

53
    inline void __aligned_free(void* p, std::size_t) noexcept
54
    {
55
        std::free(p);
175,392✔
56
    }
57
}    // namespace hpx::util::detail
58

59
#elif defined(HPX_HAVE_C11_ALIGNED_ALLOC)
60

61
#include <stdlib.h>
62

63
namespace hpx::util::detail {
64

65
    [[nodiscard]] inline void* __aligned_alloc(
66
        std::size_t alignment, std::size_t size) noexcept
67
    {
68
        return aligned_alloc(alignment, size);
69
    }
70

71
    inline void __aligned_free(void* p, std::size_t) noexcept
72
    {
73
        free(p);
74
    }
75
}    // namespace hpx::util::detail
76

77
#else    // !HPX_HAVE_CXX17_STD_ALIGNED_ALLOC && !HPX_HAVE_C11_ALIGNED_ALLOC
78

79
#include <cstdlib>
80

81
namespace hpx::util::detail {
82

83
    // provide our own (simple) implementation of aligned_alloc
84
    [[nodiscard]] inline void* __aligned_alloc(
85
        std::size_t alignment, std::size_t size) noexcept
86
    {
87
        if (alignment < alignof(void*))
88
        {
89
            alignment = alignof(void*);
90
        }
91

92
        std::size_t space = size + alignment - 1;
93
        void* allocated_mem = std::malloc(space + sizeof(void*));
94
        if (allocated_mem == nullptr)
95
        {
96
            return nullptr;
97
        }
98

99
        auto aligned_mem = static_cast<void*>(
100
            static_cast<char*>(allocated_mem) + sizeof(void*));
101

102
        std::align(alignment, size, aligned_mem, space);
103
        *(static_cast<void**>(aligned_mem) - 1) = allocated_mem;    //-V206
104

105
        return aligned_mem;
106
    }
107

108
    inline void __aligned_free(void* p, std::size_t) noexcept
109
    {
110
        if (nullptr != p)
111
        {
112
            std::free(*(static_cast<void**>(p) - 1));    //-V206
113
        }
114
    }
115
}    // namespace hpx::util::detail
116

117
#endif
118

119
namespace hpx::util::detail {
120

121
    template <typename Allocator>
122
    [[nodiscard]] void* __aligned_alloc(Allocator const& alloc,
123
        std::size_t alignment, std::size_t size) noexcept
124
    {
125
        using value_type =
126
            typename std::allocator_traits<Allocator>::value_type;
127
        using char_alloc = typename std::allocator_traits<
128
            Allocator>::template rebind_alloc<char>;
129

130
        std::size_t const s = size * sizeof(value_type);
131
        std::size_t space = s + alignment - 1;
132

133
        char_alloc a(alloc);
134
        void* allocated_mem = a.allocate(space + sizeof(void*));
135
        if (allocated_mem == nullptr)
136
        {
137
            return nullptr;
138
        }
139

140
        auto aligned_mem = static_cast<void*>(
141
            static_cast<char*>(allocated_mem) + sizeof(void*));
142

143
        std::align(alignment, size, aligned_mem, space);
144
        *(static_cast<void**>(aligned_mem) - 1) = allocated_mem;    //-V206
145

146
        return aligned_mem;
147
    }
148

149
    template <typename T>
150
    [[nodiscard]] void* __aligned_alloc(std::allocator<T> const&,
151
        std::size_t alignment, std::size_t size) noexcept
152
    {
153
        return __aligned_alloc(alignment, size);
154
    }
155

156
    template <typename Allocator>
157
    void __aligned_free(
158
        Allocator const& alloc, void* p, std::size_t size) noexcept
159
    {
160
        if (nullptr != p)
161
        {
162
            using char_alloc = typename std::allocator_traits<
163
                Allocator>::template rebind_alloc<char>;
164

165
            char_alloc a(alloc);
166
            a.deallocate(*(static_cast<void**>(p) - 1), size);    //-V206
167
        }
168
    }
169

170
    template <typename T>
171
    inline void __aligned_free(
172
        std::allocator<T> const&, void* p, std::size_t size) noexcept
173
    {
174
        __aligned_free(p, size);
175
    }
176
}    // namespace hpx::util::detail
177

178
#include <hpx/config/warnings_prefix.hpp>
179

180
namespace hpx::util {
181

182
    ///////////////////////////////////////////////////////////////////////////
183
    HPX_CXX_EXPORT template <typename T = int,
184
        typename Allocator = std::allocator<T>>
185
    struct aligned_allocator
186
    {
187
    private:
188
        HPX_NO_UNIQUE_ADDRESS Allocator alloc;
189

190
    public:
191
        using value_type = T;
192
        using pointer = T*;
193
        using const_pointer = T const*;
194
        using reference = T&;
195
        using const_reference = T const&;
196
        using size_type = std::size_t;
197
        using difference_type = std::ptrdiff_t;
198

199
        template <typename U>
200
        struct rebind
201
        {
202
            using other = aligned_allocator<U>;
203
        };
204

205
        using is_always_equal = std::true_type;
206
        using propagate_on_container_move_assignment = std::true_type;
207

208
        explicit aligned_allocator(
209
            Allocator const& alloc = Allocator{}) noexcept(noexcept(std::
210
                is_nothrow_copy_constructible_v<Allocator>))
211
          : alloc(alloc)
212
        {
213
        }
214

215
        template <typename U>
216
        explicit aligned_allocator(aligned_allocator<U> const& rhs) noexcept(
217
            noexcept(std::is_nothrow_copy_constructible_v<Allocator>))
218
          : alloc(rhs.alloc)
219
        {
220
        }
221

222
        [[nodiscard]] static pointer address(reference x) noexcept
223
        {
224
            return &x;
225
        }
226

227
        [[nodiscard]] static const_pointer address(const_reference x) noexcept
228
        {
229
            return &x;
230
        }
231

59,168✔
232
        [[nodiscard]] pointer allocate(size_type n, void const* = nullptr)
233
        {
59,168✔
234
            if (max_size() < n)
235
            {
×
236
                throw std::bad_array_new_length();
237
            }
238

239
            auto p = reinterpret_cast<pointer>(
59,168✔
240
                detail::__aligned_alloc(alloc, alignof(T), n * sizeof(T)));
241

59,168✔
242
            if (p == nullptr)
243
            {
×
244
                throw std::bad_alloc();
245
            }
246

59,168✔
247
            return p;
248
        }
249

250
        void deallocate(pointer p, size_type size) noexcept
251
        {
252
            detail::__aligned_free(alloc, p, size);
253
        }
254

255
        [[nodiscard]] static constexpr size_type max_size() noexcept
256
        {
257
            return (std::numeric_limits<size_type>::max)() / sizeof(T);
258
        }
259

260
        template <typename U, typename... Args>
261
        static void construct(U* p, Args&&... args)
262
        {
263
            hpx::construct_at(p, HPX_FORWARD(Args, args)...);
264
        }
265

266
        template <typename U>
267
        static void destroy(U* p) noexcept
268
        {
269
            std::destroy_at(p);
270
        }
271
    };
272

273
    HPX_CXX_EXPORT template <typename T>
274
    [[nodiscard]] constexpr bool operator==(
275
        aligned_allocator<T> const&, aligned_allocator<T> const&) noexcept
276
    {
277
        return true;
278
    }
279

280
    HPX_CXX_EXPORT template <typename T>
281
    [[nodiscard]] constexpr bool operator!=(
282
        aligned_allocator<T> const&, aligned_allocator<T> const&) noexcept
283
    {
284
        return false;
285
    }
286
}    // namespace hpx::util
287

288
#include <hpx/config/warnings_suffix.hpp>
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc