JPL Spatial
Sound spatialization and propagation library
Loading...
Searching...
No Matches
Memory.h
Go to the documentation of this file.
1//
2// ██╗██████╗ ██╗ ██╗██████╗ ███████╗
3// ██║██╔══██╗ ██║ ██║██╔══██╗██╔════╝ ** JPLSpatial **
4// ██║██████╔╝ ██║ ██║██████╔╝███████╗
5// ██ ██║██╔═══╝ ██║ ██║██╔══██╗╚════██║ https://github.com/Jaytheway/JPLSpatial
6// ╚█████╔╝██║ ███████╗██║██████╔╝███████║
7// ╚════╝ ╚═╝ ╚══════╝╚═╝╚═════╝ ╚══════╝
8//
9// Copyright 2024 Jaroslav Pevno, JPLSpatial is offered under the terms of the ISC license:
10//
11// Permission to use, copy, modify, and/or distribute this software for any purpose with or
12// without fee is hereby granted, provided that the above copyright notice and this permission
13// notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
14// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
16// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
17// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20#pragma once
21
22#include "JPLSpatial/Core.h"
24
25#ifdef JPL_COMPILER_MSVC
26#include <malloc.h>
27#else
28#include <cstdlib>
29#endif
30#include <memory>
31#include <type_traits>
32#include <concepts>
33#include <memory_resource>
34#include <cstddef>
35
36namespace JPL
37{
38 //======================================================================
41 inline std::pmr::memory_resource* gDefaultMemoryResource = std::pmr::get_default_resource();
42 inline std::pmr::memory_resource* GetDefaultMemoryResource() noexcept { return gDefaultMemoryResource; }
43
44 //======================================================================
47 {
48 public:
49 explicit ScopedGlobalMemoryResource(std::pmr::memory_resource* resource)
50 : mPrevious(gDefaultMemoryResource)
51 {
53 }
54
59
60 private:
61 std::pmr::memory_resource* mPrevious;
62 };
63
64 //======================================================================
68 template<class T, class AllocatorType = std::allocator<T>>
70 {
71 using AForT = typename std::allocator_traits<AllocatorType>::template rebind_alloc<T>;
72 using Traits = std::allocator_traits<AForT>;
73
75
77 : mAllocator(allocator)
78 {
79 }
80
81 // Accept already-rebound allocator too
82 explicit AllocatorDeleter(const AForT& allcoator) noexcept(std::is_nothrow_copy_constructible_v<AForT>) requires (!std::same_as<AllocatorType, AForT>)
83 : mAllocator(allcoator)
84 {
85 }
86
87 JPL_INLINE void operator()(T* ptr) noexcept
88 {
89 if (!ptr)
90 return;
91 Traits::destroy(mAllocator, ptr);
92 Traits::deallocate(mAllocator, ptr, 1);
93 }
94
95 private:
96 [[no_unique_address]] AForT mAllocator{};
97 };
98
99 //======================================================================
102 template<class T>
104 {
105 public:
106 using Allocator = std::pmr::polymorphic_allocator<T>;
107 using Traits = std::allocator_traits<Allocator>;
108
109 PmrDeleter() = default;
110 explicit PmrDeleter(std::pmr::memory_resource* resource) noexcept
111 : mResource(resource)
112 {
113 }
114
115 JPL_INLINE void operator()(T* p) noexcept
116 {
117 if (!p)
118 return;
119 Allocator allocator{ mResource };
120 Traits::destroy(allocator, p);
121 Traits::deallocate(allocator, p, 1);
122 }
123 private:
124 std::pmr::memory_resource* mResource = GetDefaultMemoryResource();
125 };
126 // Sanity check
127 static_assert(std::is_move_assignable_v<PmrDeleter<int>>);
128
129 namespace Internal
130 {
131 template<class Allocator>
132 inline constexpr bool is_pmr_alloc_v =
133 std::is_same_v<
134 typename std::allocator_traits<Allocator>::template rebind_alloc<std::byte>,
135 std::pmr::polymorphic_allocator<std::byte>
136 >;
137 }
138
139 //======================================================================
143 template<class T, class Allocator, class... Args>
144 [[nodiscard]] auto allocate_unique(const Allocator& allocator, Args&&... args)
145 {
146 using AForT = typename std::allocator_traits<Allocator>::template rebind_alloc<T>;
147 using Traits = std::allocator_traits<AForT>;
148 AForT rebound(allocator);
149
150 T* raw = Traits::allocate(rebound, 1);
151
152 if constexpr (std::is_nothrow_constructible_v<T, Args...>)
153 {
154 Traits::construct(rebound, raw, std::forward<Args>(args)...);
155 }
156 else
157 {
158 try
159 {
160 Traits::construct(rebound, raw, std::forward<Args>(args)...);
161 } catch (...)
162 {
163 Traits::deallocate(rebound, raw, 1);
164 throw;
165 }
166 }
167
168 if constexpr (Internal::is_pmr_alloc_v<std::remove_cvref_t<Allocator>>)
169 {
170 using Deleter = PmrDeleter<T>;
171 return std::unique_ptr<T, Deleter>(raw, Deleter(allocator.resource()));
172 }
173 else
174 {
176 return std::unique_ptr<T, Deleter>(raw, Deleter(rebound));
177 }
178 }
179
180 //======================================================================
182 template<class T>
183 using PmrAllocator = std::pmr::polymorphic_allocator<T>;
184
185 template<class T = std::byte>
187
188 //======================================================================
190 template<class T, class ...Args>
192 {
193 return GetDefaultPmrAllocator<>().new_object<T>(std::forward<Args>(args)...);
194 }
195
197 template<class T>
198 JPL_INLINE void DefaultDelete(T* object)
199 {
200 GetDefaultPmrAllocator<>().delete_object(object);
201 }
202
203 //======================================================================
205 template<class T, class... Args>
206 [[nodiscard]] JPL_INLINE std::shared_ptr<T> make_pmr_shared(Args&&... args)
207 {
208 return std::allocate_shared<T>(GetDefaultPmrAllocator<T>(), std::forward<Args>(args)...);
209 }
210
214 template<class T>
215 [[nodiscard]] JPL_INLINE std::shared_ptr<T> make_pmr_shared(T* ptr)
216 {
218 }
219
220 template<class T, class Y>
225 template<class T>
226 JPL_INLINE void reset_pmr_shared(std::shared_ptr<T>& sharedPtr)
227 {
228 sharedPtr.reset(static_cast<T*>(nullptr), PmrDeleter<T>(GetDefaultMemoryResource()), GetDefaultPmrAllocator<T>());
229 }
230
232 template<class T>
233 using pmr_unique_ptr = std::unique_ptr<T, PmrDeleter<T>>;
234
236 template<class T, class... Args>
241
242 //======================================================================
246 class CountingResource : public std::pmr::memory_resource
247 {
248 public:
249 explicit CountingResource(std::pmr::memory_resource* upstream)
251 {
252 }
253
254 private:
255 [[nodiscard]] JPL_INLINE void* do_allocate(std::size_t bytes, std::size_t align) override
256 {
257 void* p = Upstream->allocate(bytes, align);
258 InUse += bytes;
259 if (InUse > MaxUsage)
260 MaxUsage = InUse;
261
262 return p;
263 }
264
265 JPL_INLINE void do_deallocate(void* p, std::size_t bytes, std::size_t align) override
266 {
267 InUse -= bytes;
268 Upstream->deallocate(p, bytes, align);
269 }
270
271 [[nodiscard]] JPL_INLINE bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override
272 {
273 return this == &other;
274 }
275
276 public:
277 std::pmr::memory_resource* Upstream;
278 std::size_t InUse = 0;
279 std::size_t MaxUsage = 0;
280 };
281
282 //======================================================================
284 {
285 public:
286 [[nodiscard]] JPL_INLINE static void* Allocate(std::size_t inSize)
287 {
288 JPL_ASSERT(inSize > 0);
289 return std::malloc(inSize);
290 }
291
292 [[nodiscard]] JPL_INLINE static void* Reallocate(void* inBlock, [[maybe_unused]] std::size_t inOldSize, std::size_t inNewSize)
293 {
295 return std::realloc(inBlock, inNewSize);
296 }
297
298 JPL_INLINE static void Free(void* inBlock)
299 {
300 std::free(inBlock);
301 }
302
303 [[nodiscard]] JPL_INLINE static void* AlignedAllocate(std::size_t inSize, std::size_t inAlignment)
304 {
305 JPL_ASSERT(inSize > 0 && inAlignment > 0);
306
307#if defined(JPL_PLATFORM_WINDOWS)
308 // Microsoft doesn't implement posix_memalign
310#else
311 void* block = nullptr;
313 JPL_GCC_SUPPRESS_WARNING("-Wunused-result")
314 JPL_CLANG_SUPPRESS_WARNING("-Wunused-result")
317 return block;
318#endif
319 }
320
321 JPL_INLINE static void AlignedFree(void* inBlock)
322 {
323#if defined(JPL_PLATFORM_WINDOWS)
325#else
326 free(inBlock);
327#endif
328 }
329 };
330
331 //======================================================================
332 class PmrMallocResource : public std::pmr::memory_resource
333 {
334 public:
335 PmrMallocResource() = default;
336
337 private:
338 [[nodiscard]] JPL_INLINE void* do_allocate(std::size_t bytes, std::size_t align) override
339 {
342 else
344 }
345
346 JPL_INLINE void do_deallocate(void* p, std::size_t bytes, std::size_t align) override
347 {
350 else
352 }
353
354 [[nodiscard]] JPL_INLINE bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override
355 {
356 return this == &other;
357 }
358 };
359} // namespace JPL
#define JPL_DEFAULT_NEW_ALIGNMENT
Definition Core.h:357
#define JPL_GCC_SUPPRESS_WARNING(w)
Definition Core.h:283
#define JPL_CLANG_SUPPRESS_WARNING(w)
Definition Core.h:272
#define JPL_ASSERT(inExpression,...)
Main assert macro, usage: JPL_ASSERT(condition, message) or JPL_ASSERT(condition)
Definition ErrorReporting.h:76
Definition Memory.h:247
std::size_t MaxUsage
Definition Memory.h:279
CountingResource(std::pmr::memory_resource *upstream)
Definition Memory.h:249
std::pmr::memory_resource * Upstream
Definition Memory.h:277
std::size_t InUse
Definition Memory.h:278
Definition Memory.h:284
static JPL_INLINE void * Allocate(std::size_t inSize)
Definition Memory.h:286
static JPL_INLINE void AlignedFree(void *inBlock)
Definition Memory.h:321
static JPL_INLINE void Free(void *inBlock)
Definition Memory.h:298
static JPL_INLINE void * AlignedAllocate(std::size_t inSize, std::size_t inAlignment)
Definition Memory.h:303
static JPL_INLINE void * Reallocate(void *inBlock, std::size_t inOldSize, std::size_t inNewSize)
Definition Memory.h:292
Definition Memory.h:104
PmrDeleter()=default
std::pmr::polymorphic_allocator< T > Allocator
Definition Memory.h:106
JPL_INLINE void operator()(T *p) noexcept
Definition Memory.h:115
std::allocator_traits< Allocator > Traits
Definition Memory.h:107
PmrDeleter(std::pmr::memory_resource *resource) noexcept
Definition Memory.h:110
Definition Memory.h:333
RAII override library-wide default memory resource.
Definition Memory.h:47
ScopedGlobalMemoryResource(std::pmr::memory_resource *resource)
Definition Memory.h:49
~ScopedGlobalMemoryResource()
Definition Memory.h:55
Definition AcousticMaterial.h:36
JPL_INLINE T * DefaultNew(Args &&...args)
Allocate new object from deafult global memory resource used in JPLSpatial.
Definition Memory.h:191
JPL_INLINE void reset_pmr_shared(std::shared_ptr< T > &sharedPtr, Y *ptr)
Definition Memory.h:221
JPL_INLINE std::shared_ptr< T > make_pmr_shared(Args &&... args)
std::make_shared wrapper using our global memory resource
Definition Memory.h:206
std::unique_ptr< T, PmrDeleter< T > > pmr_unique_ptr
Alias for unique ptr using pmr allocator and deleter.
Definition Memory.h:233
JPL_INLINE void DefaultDelete(T *object)
Delete object allcoated from deafult global memory resource. The object must had been allocated by ca...
Definition Memory.h:198
std::pmr::memory_resource * GetDefaultMemoryResource() noexcept
Definition Memory.h:42
JPL_INLINE simd min(const simd &a, const simd &b) noexcept
Element-wise min.
Definition SIMD.h:1813
std::pmr::memory_resource * gDefaultMemoryResource
Definition Memory.h:41
std::pmr::polymorphic_allocator< T > PmrAllocator
Just a shorter alias.
Definition Memory.h:183
auto allocate_unique(const Allocator &allocator, Args &&... args)
Definition Memory.h:144
JPL_INLINE PmrAllocator< T > GetDefaultPmrAllocator()
Definition Memory.h:186
JPL_INLINE pmr_unique_ptr< T > make_pmr_unique(Args &&... args)
std::make_unique wrapper using our global memory resource
Definition Memory.h:237
Definition ChannelMap.h:268
Definition Memory.h:70
typename std::allocator_traits< AllocatorType >::template rebind_alloc< T > AForT
Definition Memory.h:71
AllocatorDeleter() noexcept(std::is_nothrow_default_constructible_v< AForT >)=default
JPL_INLINE void operator()(T *ptr) noexcept
Definition Memory.h:87
std::allocator_traits< AForT > Traits
Definition Memory.h:72
AllocatorDeleter(const AForT &allcoator) noexcept(std::is_nothrow_copy_constructible_v< AForT >)
Definition Memory.h:82