diff options
Diffstat (limited to 'PxShared/src/foundation/include/PsAllocator.h')
| -rw-r--r-- | PxShared/src/foundation/include/PsAllocator.h | 367 |
1 files changed, 367 insertions, 0 deletions
diff --git a/PxShared/src/foundation/include/PsAllocator.h b/PxShared/src/foundation/include/PsAllocator.h new file mode 100644 index 0000000..cbf32d3 --- /dev/null +++ b/PxShared/src/foundation/include/PsAllocator.h @@ -0,0 +1,367 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2017 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PSFOUNDATION_PSALLOCATOR_H +#define PSFOUNDATION_PSALLOCATOR_H + +#include "foundation/PxAllocatorCallback.h" +#include "foundation/PxFoundation.h" +#include "Ps.h" +#include "foundation/PxAssert.h" + +#if(PX_WINDOWS_FAMILY || PX_XBOXONE) +#include <exception> +#include <typeinfo.h> +#endif +#if(PX_APPLE_FAMILY) +#include <typeinfo> +#endif + +#include <new> + +// Allocation macros going through user allocator +#if PX_CHECKED +#define PX_ALLOC(n, name) physx::shdfnd::NamedAllocator(name).allocate(n, __FILE__, __LINE__) +#else +#define PX_ALLOC(n, name) physx::shdfnd::NonTrackingAllocator().allocate(n, __FILE__, __LINE__) +#endif +#define PX_ALLOC_TEMP(n, name) PX_ALLOC(n, name) +#define PX_FREE(x) physx::shdfnd::NonTrackingAllocator().deallocate(x) +#define PX_FREE_AND_RESET(x) \ + { \ + PX_FREE(x); \ + x = 0; \ + } + +// The following macros support plain-old-types and classes derived from UserAllocated. +#define PX_NEW(T) new (physx::shdfnd::ReflectionAllocator<T>(), __FILE__, __LINE__) T +#define PX_NEW_TEMP(T) PX_NEW(T) +#define PX_DELETE(x) delete x +#define PX_DELETE_AND_RESET(x) \ + { \ + PX_DELETE(x); \ + x = 0; \ + } +#define PX_DELETE_POD(x) \ + { \ + PX_FREE(x); \ + x = 0; \ + } +#define PX_DELETE_ARRAY(x) \ + { \ + PX_DELETE([] x); \ + x = 0; \ + } + +// aligned allocation +#define PX_ALIGNED16_ALLOC(n) physx::shdfnd::AlignedAllocator<16>().allocate(n, __FILE__, __LINE__) +#define PX_ALIGNED16_FREE(x) physx::shdfnd::AlignedAllocator<16>().deallocate(x) + +//! placement new macro to make it easy to spot bad use of 'new' +#define PX_PLACEMENT_NEW(p, T) new (p) T + +#if PX_DEBUG || PX_CHECKED +#define PX_USE_NAMED_ALLOCATOR 1 +#else +#define PX_USE_NAMED_ALLOCATOR 0 +#endif + +// Don't use inline for alloca !!! +#if PX_WINDOWS_FAMILY +#include <malloc.h> +#define PxAlloca(x) _alloca(x) +#elif PX_LINUX || PX_ANDROID +#include <malloc.h> +#define PxAlloca(x) alloca(x) +#elif PX_APPLE_FAMILY +#include <alloca.h> +#define PxAlloca(x) alloca(x) +#elif PX_PS4 +#include <memory.h> +#define PxAlloca(x) alloca(x) +#elif PX_XBOXONE +#include <malloc.h> +#define PxAlloca(x) alloca(x) +#elif PX_NX +#include <malloc.h> +#define PxAlloca(x) alloca(x) +#endif + +#define PxAllocaAligned(x, alignment) ((size_t(PxAlloca(x + alignment)) + (alignment - 1)) & ~size_t(alignment - 1)) + +namespace physx +{ +namespace shdfnd +{ + +PX_FOUNDATION_API PxAllocatorCallback& getAllocator(); + +/** +Allocator used to access the global PxAllocatorCallback instance without providing additional information. +*/ + +class PX_FOUNDATION_API Allocator +{ + public: + Allocator(const char* = 0) + { + } + void* allocate(size_t size, const char* file, int line); + void deallocate(void* ptr); +}; + +/* + * Bootstrap allocator using malloc/free. + * Don't use unless your objects get allocated before foundation is initialized. + */ +class RawAllocator +{ + public: + RawAllocator(const char* = 0) + { + } + void* allocate(size_t size, const char*, int) + { + // malloc returns valid pointer for size==0, no need to check + return ::malloc(size); + } + void deallocate(void* ptr) + { + // free(0) is guaranteed to have no side effect, no need to check + ::free(ptr); + } +}; + +/* + * Allocator that simply calls straight back to the application without tracking. + * This is used by the heap (Foundation::mNamedAllocMap) that tracks allocations + * because it needs to be able to grow as a result of an allocation. + * Making the hash table re-entrant to deal with this may not make sense. + */ +class NonTrackingAllocator +{ + public: + PX_FORCE_INLINE NonTrackingAllocator(const char* = 0) + { + } + PX_FORCE_INLINE void* allocate(size_t size, const char* file, int line) + { + return !size ? 0 : getAllocator().allocate(size, "NonTrackedAlloc", file, line); + } + PX_FORCE_INLINE void deallocate(void* ptr) + { + if(ptr) + getAllocator().deallocate(ptr); + } +}; + +/* +\brief Virtual allocator callback used to provide run-time defined allocators to foundation types like Array or Bitmap. + This is used by VirtualAllocator +*/ +class VirtualAllocatorCallback +{ + public: + VirtualAllocatorCallback() + { + } + virtual ~VirtualAllocatorCallback() + { + } + virtual void* allocate(const size_t size, const char* file, const int line) = 0; + virtual void deallocate(void* ptr) = 0; +}; + +/* +\brief Virtual allocator to be used by foundation types to provide run-time defined allocators. +Due to the fact that Array extends its allocator, rather than contains a reference/pointer to it, the VirtualAllocator +must +be a concrete type containing a pointer to a virtual callback. The callback may not be available at instantiation time, +therefore +methods are provided to set the callback later. +*/ +class VirtualAllocator +{ + public: + VirtualAllocator(VirtualAllocatorCallback* callback = NULL) : mCallback(callback) + { + } + + void* allocate(const size_t size, const char* file, const int line) + { + PX_ASSERT(mCallback); + if(size) + return mCallback->allocate(size, file, line); + return NULL; + } + void deallocate(void* ptr) + { + PX_ASSERT(mCallback); + if(ptr) + mCallback->deallocate(ptr); + } + + void setCallback(VirtualAllocatorCallback* callback) + { + mCallback = callback; + } + VirtualAllocatorCallback* getCallback() + { + return mCallback; + } + + private: + VirtualAllocatorCallback* mCallback; + VirtualAllocator& operator=(const VirtualAllocator&); +}; + +#if PX_USE_NAMED_ALLOCATOR // can be slow, so only use in debug/checked +class PX_FOUNDATION_API NamedAllocator +{ + public: + NamedAllocator(const PxEMPTY); + NamedAllocator(const char* name = 0); // todo: should not have default argument! + NamedAllocator(const NamedAllocator&); + ~NamedAllocator(); + NamedAllocator& operator=(const NamedAllocator&); + void* allocate(size_t size, const char* filename, int line); + void deallocate(void* ptr); +}; +#else +class NamedAllocator; +#endif // PX_DEBUG + +/** +Allocator used to access the global PxAllocatorCallback instance using a static name derived from T. +*/ + +template <typename T> +class ReflectionAllocator +{ + static const char* getName() + { + if(!PxGetFoundation().getReportAllocationNames()) + return "<allocation names disabled>"; +#if PX_GCC_FAMILY + return __PRETTY_FUNCTION__; +#else + // name() calls malloc(), raw_name() wouldn't + return typeid(T).name(); +#endif + } + + public: + ReflectionAllocator(const PxEMPTY) + { + } + ReflectionAllocator(const char* = 0) + { + } + inline ReflectionAllocator(const ReflectionAllocator&) + { + } + void* allocate(size_t size, const char* filename, int line) + { + return size ? getAllocator().allocate(size, getName(), filename, line) : 0; + } + void deallocate(void* ptr) + { + if(ptr) + getAllocator().deallocate(ptr); + } +}; + +template <typename T> +struct AllocatorTraits +{ +#if PX_USE_NAMED_ALLOCATOR + typedef NamedAllocator Type; +#else + typedef ReflectionAllocator<T> Type; +#endif +}; + +// if you get a build error here, you are trying to PX_NEW a class +// that is neither plain-old-type nor derived from UserAllocated +template <typename T, typename X> +union EnableIfPod +{ + int i; + T t; + typedef X Type; +}; + +} // namespace shdfnd +} // namespace physx + +// Global placement new for ReflectionAllocator templated by +// plain-old-type. Allows using PX_NEW for pointers and built-in-types. +// +// ATTENTION: You need to use PX_DELETE_POD or PX_FREE to deallocate +// memory, not PX_DELETE. PX_DELETE_POD redirects to PX_FREE. +// +// Rationale: PX_DELETE uses global operator delete(void*), which we dont' want to overload. +// Any other definition of PX_DELETE couldn't support array syntax 'PX_DELETE([]a);'. +// PX_DELETE_POD was preferred over PX_DELETE_ARRAY because it is used +// less often and applies to both single instances and arrays. +template <typename T> +PX_INLINE void* operator new(size_t size, physx::shdfnd::ReflectionAllocator<T> alloc, const char* fileName, + typename physx::shdfnd::EnableIfPod<T, int>::Type line) +{ + return alloc.allocate(size, fileName, line); +} + +template <typename T> +PX_INLINE void* operator new [](size_t size, physx::shdfnd::ReflectionAllocator<T> alloc, const char* fileName, + typename physx::shdfnd::EnableIfPod<T, int>::Type line) +{ return alloc.allocate(size, fileName, line); } + +// If construction after placement new throws, this placement delete is being called. +template <typename T> +PX_INLINE void operator delete(void* ptr, physx::shdfnd::ReflectionAllocator<T> alloc, const char* fileName, + typename physx::shdfnd::EnableIfPod<T, int>::Type line) +{ + PX_UNUSED(fileName); + PX_UNUSED(line); + + alloc.deallocate(ptr); +} + +// If construction after placement new throws, this placement delete is being called. +template <typename T> +PX_INLINE void operator delete [](void* ptr, physx::shdfnd::ReflectionAllocator<T> alloc, const char* fileName, + typename physx::shdfnd::EnableIfPod<T, int>::Type line) +{ + PX_UNUSED(fileName); + PX_UNUSED(line); + + alloc.deallocate(ptr); +} + +#endif // #ifndef PSFOUNDATION_PSALLOCATOR_H |