Jolt Physics
A multi core friendly Game Physics Engine
Loading...
Searching...
No Matches
STLLocalAllocator.h
Go to the documentation of this file.
1// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2// SPDX-FileCopyrightText: 2025 Jorrit Rouwe
3// SPDX-License-Identifier: MIT
4
5#pragma once
6
8
10
11#ifndef JPH_DISABLE_CUSTOM_ALLOCATOR
12
14template <typename T, size_t N>
16{
17 using Base = STLAllocator<T>;
18
19public:
21 using value_type = T;
22 using pointer = T *;
23 using const_pointer = const T *;
24 using reference = T &;
25 using const_reference = const T &;
26 using size_type = size_t;
27 using difference_type = ptrdiff_t;
28
30 using is_always_equal = std::false_type;
31
35 using propagate_on_container_swap = std::false_type;
36
38 STLLocalAllocator() = default;
39 STLLocalAllocator(const STLLocalAllocator &) = delete; // Can't copy an allocator as the buffer is local to the original
40 STLLocalAllocator(STLLocalAllocator &&) = delete; // Can't move an allocator as the buffer is local to the original
41 STLLocalAllocator & operator = (const STLLocalAllocator &) = delete; // Can't copy an allocator as the buffer is local to the original
42
46 template <class T2>
47 explicit STLLocalAllocator(const STLLocalAllocator<T2, N> &) : mNumElementsUsed(N) { }
48
50 inline bool is_local(const_pointer inPointer) const
51 {
52 ptrdiff_t diff = inPointer - reinterpret_cast<const_pointer>(mElements);
53 return diff >= 0 && diff < ptrdiff_t(N);
54 }
55
58 {
59 // If we allocate more than we have, fall back to the heap
60 if (mNumElementsUsed + inN > N)
61 return Base::allocate(inN);
62
63 // Allocate from our local buffer
64 pointer result = reinterpret_cast<pointer>(mElements) + mNumElementsUsed;
65 mNumElementsUsed += inN;
66 return result;
67 }
68
70 static constexpr bool has_reallocate = true;
71
73 inline pointer reallocate(pointer inOldPointer, size_type inOldSize, size_type inNewSize)
74 {
75 JPH_ASSERT(inNewSize > 0); // Reallocating to zero size is implementation dependent, so we don't allow it
76
77 // If there was no previous allocation, we can go through the regular allocate function
78 if (inOldPointer == nullptr)
79 return allocate(inNewSize);
80
81 // If the pointer is outside our local buffer, fall back to the heap
82 if (!is_local(inOldPointer))
83 {
85 return Base::reallocate(inOldPointer, inOldSize, inNewSize);
86 else
87 return ReallocateImpl(inOldPointer, inOldSize, inNewSize);
88 }
89
90 // If we happen to have space left, we only need to update our bookkeeping
91 pointer base_ptr = reinterpret_cast<pointer>(mElements) + mNumElementsUsed - inOldSize;
92 if (inOldPointer == base_ptr
93 && mNumElementsUsed - inOldSize + inNewSize <= N)
94 {
95 mNumElementsUsed += inNewSize - inOldSize;
96 return base_ptr;
97 }
98
99 // We can't reallocate in place, fall back to the heap
100 return ReallocateImpl(inOldPointer, inOldSize, inNewSize);
101 }
102
104 inline void deallocate(pointer inPointer, size_type inN)
105 {
106 // If the pointer is not in our local buffer, fall back to the heap
107 if (!is_local(inPointer))
108 return Base::deallocate(inPointer, inN);
109
110 // Else we can only reclaim memory if it was the last allocation
111 if (inPointer == reinterpret_cast<pointer>(mElements) + mNumElementsUsed - inN)
112 mNumElementsUsed -= inN;
113 }
114
116 inline bool operator == (const STLLocalAllocator<T, N> &inRHS) const
117 {
118 return this == &inRHS;
119 }
120
121 inline bool operator != (const STLLocalAllocator<T, N> &inRHS) const
122 {
123 return this != &inRHS;
124 }
125
127 template <typename T2>
128 struct rebind
129 {
131 };
132
133private:
135 inline pointer ReallocateImpl(pointer inOldPointer, size_type inOldSize, size_type inNewSize)
136 {
137 pointer new_pointer = Base::allocate(inNewSize);
138 size_type n = min(inOldSize, inNewSize);
139 if constexpr (std::is_trivially_copyable<T>())
140 {
141 // Can use mem copy
142 memcpy(new_pointer, inOldPointer, n * sizeof(T));
143 }
144 else
145 {
146 // Need to actually move the elements
147 for (size_t i = 0; i < n; ++i)
148 {
149 new (new_pointer + i) T(std::move(inOldPointer[i]));
150 inOldPointer[i].~T();
151 }
152 }
153 deallocate(inOldPointer, inOldSize);
154 return new_pointer;
155 }
156
157 alignas(T) uint8 mElements[N * sizeof(T)];
158 size_type mNumElementsUsed = 0;
159};
160
162template <class T, size_t N> struct AllocatorHasReallocate<STLLocalAllocator<T, N>> { static constexpr bool sValue = STLLocalAllocator<T, N>::has_reallocate; };
163
164#else
165
166template <typename T, size_t N> using STLLocalAllocator = std::allocator<T>;
167
168#endif // !JPH_DISABLE_CUSTOM_ALLOCATOR
169
std::uint8_t uint8
Definition Core.h:487
#define JPH_NAMESPACE_END
Definition Core.h:418
#define JPH_NAMESPACE_BEGIN
Definition Core.h:412
#define JPH_ASSERT(...)
Definition IssueReporting.h:33
STL allocator that forwards to our allocation functions.
Definition STLAllocator.h:17
pointer allocate(size_type inN)
Allocate memory.
Definition STLAllocator.h:50
pointer reallocate(pointer inOldPointer, size_type inOldSize, size_type inNewSize)
Reallocate memory.
Definition STLAllocator.h:63
void deallocate(pointer inPointer, size_type)
Free memory.
Definition STLAllocator.h:70
STL allocator that keeps N elements in a local buffer before falling back to regular allocations.
Definition STLLocalAllocator.h:16
STLLocalAllocator & operator=(const STLLocalAllocator &)=delete
std::false_type propagate_on_container_swap
Definition STLLocalAllocator.h:35
void deallocate(pointer inPointer, size_type inN)
Free memory.
Definition STLLocalAllocator.h:104
const T & const_reference
Definition STLLocalAllocator.h:25
std::false_type is_always_equal
The allocator is not stateless (has local buffer)
Definition STLLocalAllocator.h:30
size_t size_type
Definition STLLocalAllocator.h:26
static constexpr bool has_reallocate
Always implements a reallocate function as we can often reallocate in place.
Definition STLLocalAllocator.h:70
T & reference
Definition STLLocalAllocator.h:24
STLLocalAllocator(const STLLocalAllocator< T2, N > &)
Definition STLLocalAllocator.h:47
STLLocalAllocator(STLLocalAllocator &&)=delete
STLLocalAllocator()=default
Constructor.
bool operator==(const STLLocalAllocator< T, N > &inRHS) const
Allocators are not-stateless, assume if allocator address matches that the allocators are the same.
Definition STLLocalAllocator.h:116
bool operator!=(const STLLocalAllocator< T, N > &inRHS) const
Definition STLLocalAllocator.h:121
const T * const_pointer
Definition STLLocalAllocator.h:23
std::false_type propagate_on_container_move_assignment
Definition STLLocalAllocator.h:34
T * pointer
Definition STLLocalAllocator.h:22
T value_type
General properties.
Definition STLLocalAllocator.h:21
STLLocalAllocator(const STLLocalAllocator &)=delete
pointer allocate(size_type inN)
Allocate memory.
Definition STLLocalAllocator.h:57
ptrdiff_t difference_type
Definition STLLocalAllocator.h:27
pointer reallocate(pointer inOldPointer, size_type inOldSize, size_type inNewSize)
Reallocate memory.
Definition STLLocalAllocator.h:73
std::false_type propagate_on_container_copy_assignment
We cannot copy, move or swap allocators.
Definition STLLocalAllocator.h:33
bool is_local(const_pointer inPointer) const
Check if inPointer is in the local buffer.
Definition STLLocalAllocator.h:50
Default implementation of AllocatorHasReallocate which tells if an allocator has a reallocate functio...
Definition STLAllocator.h:10
static constexpr bool sValue
Definition STLAllocator.h:10
Converting to allocator for other type.
Definition STLLocalAllocator.h:129