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> STLLocalAllocator(const STLLocalAllocator<T2, N> &) : mNumElementsUsed(N) { }
47
49 inline bool is_local(const_pointer inPointer) const
50 {
51 ptrdiff_t diff = inPointer - reinterpret_cast<const_pointer>(mElements);
52 return diff >= 0 && diff < ptrdiff_t(N);
53 }
54
57 {
58 // If we allocate more than we have, fall back to the heap
59 if (mNumElementsUsed + inN > N)
60 return Base::allocate(inN);
61
62 // Allocate from our local buffer
63 pointer result = reinterpret_cast<pointer>(mElements) + mNumElementsUsed;
64 mNumElementsUsed += inN;
65 return result;
66 }
67
69 static constexpr bool has_reallocate = true;
70
72 inline pointer reallocate(pointer inOldPointer, size_type inOldSize, size_type inNewSize)
73 {
74 JPH_ASSERT(inNewSize > 0); // Reallocating to zero size is implementation dependent, so we don't allow it
75
76 // If there was no previous allocation, we can go through the regular allocate function
77 if (inOldPointer == nullptr)
78 return allocate(inNewSize);
79
80 // If the pointer is outside our local buffer, fall back to the heap
81 if (!is_local(inOldPointer))
82 {
84 return Base::reallocate(inOldPointer, inOldSize, inNewSize);
85 else
86 return ReallocateImpl(inOldPointer, inOldSize, inNewSize);
87 }
88
89 // If we happen to have space left, we only need to update our bookkeeping
90 pointer base_ptr = reinterpret_cast<pointer>(mElements) + mNumElementsUsed - inOldSize;
91 if (inOldPointer == base_ptr
92 && mNumElementsUsed - inOldSize + inNewSize <= N)
93 {
94 mNumElementsUsed += inNewSize - inOldSize;
95 return base_ptr;
96 }
97
98 // We can't reallocate in place, fall back to the heap
99 return ReallocateImpl(inOldPointer, inOldSize, inNewSize);
100 }
101
103 inline void deallocate(pointer inPointer, size_type inN)
104 {
105 // If the pointer is not in our local buffer, fall back to the heap
106 if (!is_local(inPointer))
107 return Base::deallocate(inPointer, inN);
108
109 // Else we can only reclaim memory if it was the last allocation
110 if (inPointer == reinterpret_cast<pointer>(mElements) + mNumElementsUsed - inN)
111 mNumElementsUsed -= inN;
112 }
113
115 inline bool operator == (const STLLocalAllocator<T, N> &inRHS) const
116 {
117 return this == &inRHS;
118 }
119
120 inline bool operator != (const STLLocalAllocator<T, N> &inRHS) const
121 {
122 return this != &inRHS;
123 }
124
126 template <typename T2>
127 struct rebind
128 {
130 };
131
132private:
134 inline pointer ReallocateImpl(pointer inOldPointer, size_type inOldSize, size_type inNewSize)
135 {
136 pointer new_pointer = Base::allocate(inNewSize);
137 size_type n = min(inOldSize, inNewSize);
138 if constexpr (std::is_trivially_copyable<T>())
139 {
140 // Can use mem copy
141 memcpy(new_pointer, inOldPointer, n * sizeof(T));
142 }
143 else
144 {
145 // Need to actually move the elements
146 for (size_t i = 0; i < n; ++i)
147 {
148 new (new_pointer + i) T(std::move(inOldPointer[i]));
149 inOldPointer[i].~T();
150 }
151 }
152 deallocate(inOldPointer, inOldSize);
153 return new_pointer;
154 }
155
156 alignas(T) uint8 mElements[N * sizeof(T)];
157 size_type mNumElementsUsed = 0;
158};
159
161template <class T, size_t N> struct AllocatorHasReallocate<STLLocalAllocator<T, N>> { static constexpr bool sValue = STLLocalAllocator<T, N>::has_reallocate; };
162
163#else
164
165template <typename T, size_t N> using STLLocalAllocator = std::allocator<T>;
166
167#endif // !JPH_DISABLE_CUSTOM_ALLOCATOR
168
std::uint8_t uint8
Definition Core.h:482
#define JPH_NAMESPACE_END
Definition Core.h:414
#define JPH_NAMESPACE_BEGIN
Definition Core.h:408
#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:103
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:69
T & reference
Definition STLLocalAllocator.h:24
STLLocalAllocator(const STLLocalAllocator< T2, N > &)
Definition STLLocalAllocator.h:46
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:115
bool operator!=(const STLLocalAllocator< T, N > &inRHS) const
Definition STLLocalAllocator.h:120
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:56
ptrdiff_t difference_type
Definition STLLocalAllocator.h:27
pointer reallocate(pointer inOldPointer, size_type inOldSize, size_type inNewSize)
Reallocate memory.
Definition STLLocalAllocator.h:72
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:49
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:128