1//
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions
4// are met:
5// * Redistributions of source code must retain the above copyright
6// notice, this list of conditions and the following disclaimer.
7// * Redistributions in binary form must reproduce the above copyright
8// notice, this list of conditions and the following disclaimer in the
9// documentation and/or other materials provided with the distribution.
10// * Neither the name of NVIDIA CORPORATION nor the names of its
11// contributors may be used to endorse or promote products derived
12// from this software without specific prior written permission.
13//
14// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
15// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25//
26// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
27// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
28// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
29
30#ifndef PSFOUNDATION_PSALLOCATOR_H
31#define PSFOUNDATION_PSALLOCATOR_H
32
33#include "foundation/PxAllocatorCallback.h"
34#include "foundation/PxAssert.h"
35#include "PxFoundation.h"
36#include "Ps.h"
37
38#if(PX_WINDOWS_FAMILY || PX_XBOXONE || PX_XBOX_SERIES_X)
39 #include <exception>
40 #if(_MSC_VER >= 1923)
41 #include <typeinfo>
42 #else
43 #include <typeinfo.h>
44 #endif
45#endif
46#if(PX_APPLE_FAMILY)
47 #include <typeinfo>
48#endif
49
50#include <new>
51
52// Allocation macros going through user allocator
53#if PX_CHECKED
54 #define PX_ALLOC(n, name) physx::shdfnd::NamedAllocator(name).allocate(n, __FILE__, __LINE__)
55#else
56 #define PX_ALLOC(n, name) physx::shdfnd::NonTrackingAllocator().allocate(n, __FILE__, __LINE__)
57#endif
58#define PX_ALLOC_TEMP(n, name) PX_ALLOC(n, name)
59#define PX_FREE(x) physx::shdfnd::NonTrackingAllocator().deallocate(x)
60#define PX_FREE_AND_RESET(x) \
61 { \
62 PX_FREE(x); \
63 x = 0; \
64 }
65
66// The following macros support plain-old-types and classes derived from UserAllocated.
67#define PX_NEW(T) new (physx::shdfnd::ReflectionAllocator<T>(), __FILE__, __LINE__) T
68#define PX_NEW_TEMP(T) PX_NEW(T)
69#define PX_DELETE(x) delete x
70#define PX_DELETE_AND_RESET(x) \
71 { \
72 PX_DELETE(x); \
73 x = 0; \
74 }
75#define PX_DELETE_POD(x) \
76 { \
77 PX_FREE(x); \
78 x = 0; \
79 }
80#define PX_DELETE_ARRAY(x) \
81 { \
82 PX_DELETE([] x); \
83 x = 0; \
84 }
85
86// aligned allocation
87#define PX_ALIGNED16_ALLOC(n) physx::shdfnd::AlignedAllocator<16>().allocate(n, __FILE__, __LINE__)
88#define PX_ALIGNED16_FREE(x) physx::shdfnd::AlignedAllocator<16>().deallocate(x)
89
90//! placement new macro to make it easy to spot bad use of 'new'
91#define PX_PLACEMENT_NEW(p, T) new (p) T
92
93#if PX_DEBUG || PX_CHECKED
94 #define PX_USE_NAMED_ALLOCATOR 1
95#else
96 #define PX_USE_NAMED_ALLOCATOR 0
97#endif
98
99// Don't use inline for alloca !!!
100#if PX_WINDOWS_FAMILY
101 #include <malloc.h>
102 #define PxAlloca(x) _alloca(x)
103#elif PX_LINUX || PX_ANDROID
104 #include <malloc.h>
105 #define PxAlloca(x) alloca(x)
106#elif PX_APPLE_FAMILY
107 #include <alloca.h>
108 #define PxAlloca(x) alloca(x)
109#elif PX_PS4
110 #include <memory.h>
111 #define PxAlloca(x) alloca(x)
112#elif PX_XBOXONE
113 #include <malloc.h>
114 #define PxAlloca(x) alloca(x)
115#elif PX_XBOX_SERIES_X
116 #include <malloc.h>
117 #define PxAlloca(x) alloca(x)
118#elif PX_SWITCH
119 #include <malloc.h>
120 #define PxAlloca(x) alloca(x)
121#endif
122
123#define PxAllocaAligned(x, alignment) ((size_t(PxAlloca(x + alignment)) + (alignment - 1)) & ~size_t(alignment - 1))
124
125namespace physx
126{
127namespace shdfnd
128{
129
130PX_FOUNDATION_API PxAllocatorCallback& getAllocator();
131
132/**
133Allocator used to access the global PxAllocatorCallback instance without providing additional information.
134*/
135
136class PX_FOUNDATION_API Allocator
137{
138 public:
139 Allocator(const char* = 0)
140 {
141 }
142 void* allocate(size_t size, const char* file, int line);
143 void deallocate(void* ptr);
144};
145
146/*
147 * Bootstrap allocator using malloc/free.
148 * Don't use unless your objects get allocated before foundation is initialized.
149 */
150class RawAllocator
151{
152 public:
153 RawAllocator(const char* = 0)
154 {
155 }
156 void* allocate(size_t size, const char*, int)
157 {
158 // malloc returns valid pointer for size==0, no need to check
159 return ::malloc(size: size);
160 }
161 void deallocate(void* ptr)
162 {
163 // free(0) is guaranteed to have no side effect, no need to check
164 ::free(ptr: ptr);
165 }
166};
167
168/*
169 * Allocator that simply calls straight back to the application without tracking.
170 * This is used by the heap (Foundation::mNamedAllocMap) that tracks allocations
171 * because it needs to be able to grow as a result of an allocation.
172 * Making the hash table re-entrant to deal with this may not make sense.
173 */
174class NonTrackingAllocator
175{
176 public:
177 PX_FORCE_INLINE NonTrackingAllocator(const char* = 0)
178 {
179 }
180 PX_FORCE_INLINE void* allocate(size_t size, const char* file, int line)
181 {
182 return !size ? 0 : getAllocator().allocate(size, typeName: "NonTrackedAlloc", filename: file, line);
183 }
184 PX_FORCE_INLINE void deallocate(void* ptr)
185 {
186 if(ptr)
187 getAllocator().deallocate(ptr);
188 }
189};
190
191/*
192\brief Virtual allocator callback used to provide run-time defined allocators to foundation types like Array or Bitmap.
193 This is used by VirtualAllocator
194*/
195class VirtualAllocatorCallback
196{
197 public:
198 VirtualAllocatorCallback()
199 {
200 }
201 virtual ~VirtualAllocatorCallback()
202 {
203 }
204 virtual void* allocate(const size_t size, const char* file, const int line) = 0;
205 virtual void deallocate(void* ptr) = 0;
206};
207
208/*
209\brief Virtual allocator to be used by foundation types to provide run-time defined allocators.
210Due to the fact that Array extends its allocator, rather than contains a reference/pointer to it, the VirtualAllocator
211must
212be a concrete type containing a pointer to a virtual callback. The callback may not be available at instantiation time,
213therefore
214methods are provided to set the callback later.
215*/
216class VirtualAllocator
217{
218 public:
219 VirtualAllocator(VirtualAllocatorCallback* callback = NULL) : mCallback(callback)
220 {
221 }
222
223 void* allocate(const size_t size, const char* file, const int line)
224 {
225 PX_ASSERT(mCallback);
226 if(size)
227 return mCallback->allocate(size, file, line);
228 return NULL;
229 }
230 void deallocate(void* ptr)
231 {
232 PX_ASSERT(mCallback);
233 if(ptr)
234 mCallback->deallocate(ptr);
235 }
236
237 void setCallback(VirtualAllocatorCallback* callback)
238 {
239 mCallback = callback;
240 }
241 VirtualAllocatorCallback* getCallback()
242 {
243 return mCallback;
244 }
245
246 private:
247 VirtualAllocatorCallback* mCallback;
248 VirtualAllocator& operator=(const VirtualAllocator&);
249};
250
251#if PX_USE_NAMED_ALLOCATOR // can be slow, so only use in debug/checked
252class PX_FOUNDATION_API NamedAllocator
253{
254 public:
255 NamedAllocator(const PxEMPTY);
256 NamedAllocator(const char* name = 0); // todo: should not have default argument!
257 NamedAllocator(const NamedAllocator&);
258 ~NamedAllocator();
259 NamedAllocator& operator=(const NamedAllocator&);
260 void* allocate(size_t size, const char* filename, int line);
261 void deallocate(void* ptr);
262};
263#else
264class NamedAllocator;
265#endif // PX_DEBUG
266
267/**
268Allocator used to access the global PxAllocatorCallback instance using a static name derived from T.
269*/
270
271template <typename T>
272class ReflectionAllocator
273{
274 static const char* getName()
275 {
276 if(!PxGetFoundation().getReportAllocationNames())
277 return "<allocation names disabled>";
278#if PX_GCC_FAMILY
279 return __PRETTY_FUNCTION__;
280#else
281 // name() calls malloc(), raw_name() wouldn't
282 return typeid(T).name();
283#endif
284 }
285
286 public:
287 ReflectionAllocator(const PxEMPTY)
288 {
289 }
290 ReflectionAllocator(const char* = 0)
291 {
292 }
293 inline ReflectionAllocator(const ReflectionAllocator&)
294 {
295 }
296 void* allocate(size_t size, const char* filename, int line)
297 {
298 return size ? getAllocator().allocate(size, typeName: getName(), filename, line) : 0;
299 }
300 void deallocate(void* ptr)
301 {
302 if(ptr)
303 getAllocator().deallocate(ptr);
304 }
305};
306
307template <typename T>
308struct AllocatorTraits
309{
310#if PX_USE_NAMED_ALLOCATOR
311 typedef NamedAllocator Type;
312#else
313 typedef ReflectionAllocator<T> Type;
314#endif
315};
316
317// if you get a build error here, you are trying to PX_NEW a class
318// that is neither plain-old-type nor derived from UserAllocated
319template <typename T, typename X>
320union EnableIfPod
321{
322 int i;
323 T t;
324 typedef X Type;
325};
326
327} // namespace shdfnd
328} // namespace physx
329
330// Global placement new for ReflectionAllocator templated by
331// plain-old-type. Allows using PX_NEW for pointers and built-in-types.
332//
333// ATTENTION: You need to use PX_DELETE_POD or PX_FREE to deallocate
334// memory, not PX_DELETE. PX_DELETE_POD redirects to PX_FREE.
335//
336// Rationale: PX_DELETE uses global operator delete(void*), which we dont' want to overload.
337// Any other definition of PX_DELETE couldn't support array syntax 'PX_DELETE([]a);'.
338// PX_DELETE_POD was preferred over PX_DELETE_ARRAY because it is used
339// less often and applies to both single instances and arrays.
340template <typename T>
341PX_INLINE void* operator new(size_t size, physx::shdfnd::ReflectionAllocator<T> alloc, const char* fileName,
342 typename physx::shdfnd::EnableIfPod<T, int>::Type line)
343{
344 return alloc.allocate(size, fileName, line);
345}
346
347template <typename T>
348PX_INLINE void* operator new [](size_t size, physx::shdfnd::ReflectionAllocator<T> alloc, const char* fileName,
349 typename physx::shdfnd::EnableIfPod<T, int>::Type line)
350{ return alloc.allocate(size, fileName, line); }
351
352// If construction after placement new throws, this placement delete is being called.
353template <typename T>
354PX_INLINE void operator delete(void* ptr, physx::shdfnd::ReflectionAllocator<T> alloc, const char* fileName,
355 typename physx::shdfnd::EnableIfPod<T, int>::Type line)
356{
357 PX_UNUSED(fileName);
358 PX_UNUSED(line);
359
360 alloc.deallocate(ptr);
361}
362
363// If construction after placement new throws, this placement delete is being called.
364template <typename T>
365PX_INLINE void operator delete [](void* ptr, physx::shdfnd::ReflectionAllocator<T> alloc, const char* fileName,
366 typename physx::shdfnd::EnableIfPod<T, int>::Type line)
367{
368 PX_UNUSED(fileName);
369 PX_UNUSED(line);
370
371 alloc.deallocate(ptr);
372}
373
374#endif // #ifndef PSFOUNDATION_PSALLOCATOR_H
375

source code of qtquick3dphysics/src/3rdparty/PhysX/source/foundation/include/PsAllocator.h