Browse Source

Ability to override memory allocations (#183)

* Override Allocate, Free, AlignedAllocate and AlignedFree if you have your own allocator
* Renamed vectors -> Array, unordered_map -> UnorderedMap,  unordered_set -> UnorderedSet, string -> String
* queue and deque using STLAllocator
* Removed usages of map
* Marked most classes as JPH_OVERRIDE_NEW_DELETE
* Removed 'mGetSupportFunctionGeometry' cache, was very rarely used and was not using the custom allocator
* Added memory allocation hook under windows that can validate that all allocations go through the custom allocator

Note: Define JPH_DISABLE_CUSTOM_ALLOCATOR to use the default allocator. In this case the standard STL types will be used again.
Jorrit Rouwe 3 years ago
parent
commit
b68097f582
100 changed files with 603 additions and 282 deletions
  1. 5 0
      Build/README.md
  2. 3 0
      HelloWorld/HelloWorld.cpp
  3. 1 1
      Jolt/AABBTree/AABBTreeBuilder.cpp
  4. 3 1
      Jolt/AABBTree/AABBTreeBuilder.h
  5. 6 4
      Jolt/AABBTree/AABBTreeToBuffer.h
  6. 1 1
      Jolt/AABBTree/NodeCodec/NodeCodecQuadTreeHalfFloat.h
  7. 3 7
      Jolt/AABBTree/TriangleCodec/TriangleCodecIndexed8BitPackSOA4Flags.h
  8. 2 2
      Jolt/Core/ByteBuffer.h
  9. 2 2
      Jolt/Core/Factory.cpp
  10. 6 7
      Jolt/Core/Factory.h
  11. 5 10
      Jolt/Core/FixedSizeFreeList.h
  12. 7 7
      Jolt/Core/FixedSizeFreeList.inl
  13. 6 0
      Jolt/Core/JobSystem.h
  14. 10 13
      Jolt/Core/JobSystemThreadPool.cpp
  15. 6 2
      Jolt/Core/JobSystemThreadPool.h
  16. 1 1
      Jolt/Core/LinearCurve.h
  17. 1 2
      Jolt/Core/LockFreeHashMap.h
  18. 4 4
      Jolt/Core/LockFreeHashMap.inl
  19. 37 4
      Jolt/Core/Memory.cpp
  20. 43 3
      Jolt/Core/Memory.h
  21. 2 0
      Jolt/Core/MutexArray.h
  22. 6 6
      Jolt/Core/Profiler.cpp
  23. 26 12
      Jolt/Core/Profiler.h
  24. 2 2
      Jolt/Core/Profiler.inl
  25. 2 0
      Jolt/Core/RTTI.h
  26. 1 1
      Jolt/Core/Reference.h
  27. 16 16
      Jolt/Core/Result.h
  28. 1 3
      Jolt/Core/STLAlignedAllocator.h
  29. 101 0
      Jolt/Core/STLAllocator.h
  30. 7 7
      Jolt/Core/StaticArray.h
  31. 6 5
      Jolt/Core/StreamIn.h
  32. 6 5
      Jolt/Core/StreamOut.h
  33. 11 11
      Jolt/Core/StringTools.cpp
  34. 8 7
      Jolt/Core/StringTools.h
  35. 9 4
      Jolt/Core/TempAllocator.h
  36. 1 1
      Jolt/Core/TickCounter.cpp
  37. 14 0
      Jolt/Core/UnorderedMap.h
  38. 14 0
      Jolt/Core/UnorderedSet.h
  39. 2 0
      Jolt/Geometry/AABox.h
  40. 8 8
      Jolt/Geometry/ConvexHullBuilder.cpp
  41. 10 6
      Jolt/Geometry/ConvexHullBuilder.h
  42. 3 3
      Jolt/Geometry/ConvexHullBuilder2D.cpp
  43. 6 4
      Jolt/Geometry/ConvexHullBuilder2D.h
  44. 2 0
      Jolt/Geometry/Ellipse.h
  45. 4 2
      Jolt/Geometry/IndexedTriangle.h
  46. 2 5
      Jolt/Geometry/Indexify.cpp
  47. 2 0
      Jolt/Geometry/OrientedBox.h
  48. 2 0
      Jolt/Geometry/Plane.h
  49. 2 0
      Jolt/Geometry/Sphere.h
  50. 3 1
      Jolt/Geometry/Triangle.h
  51. 4 1
      Jolt/Jolt.cmake
  52. 2 0
      Jolt/Jolt.h
  53. 2 0
      Jolt/Math/DVec3.h
  54. 2 0
      Jolt/Math/Float2.h
  55. 3 1
      Jolt/Math/Float3.h
  56. 2 0
      Jolt/Math/Float4.h
  57. 2 0
      Jolt/Math/Mat44.h
  58. 2 0
      Jolt/Math/Quat.h
  59. 2 0
      Jolt/Math/UVec4.h
  60. 2 0
      Jolt/Math/UVec8.h
  61. 1 5
      Jolt/Math/Vec3.cpp
  62. 2 0
      Jolt/Math/Vec3.h
  63. 2 0
      Jolt/Math/Vec4.h
  64. 2 0
      Jolt/Math/Vec8.h
  65. 2 2
      Jolt/ObjectStream/GetPrimitiveTypeOfType.h
  66. 7 7
      Jolt/ObjectStream/ObjectStream.h
  67. 2 2
      Jolt/ObjectStream/ObjectStreamBinaryIn.cpp
  68. 5 3
      Jolt/ObjectStream/ObjectStreamBinaryIn.h
  69. 3 3
      Jolt/ObjectStream/ObjectStreamBinaryOut.cpp
  70. 4 2
      Jolt/ObjectStream/ObjectStreamBinaryOut.h
  71. 7 10
      Jolt/ObjectStream/ObjectStreamIn.cpp
  72. 6 6
      Jolt/ObjectStream/ObjectStreamIn.h
  73. 8 6
      Jolt/ObjectStream/ObjectStreamOut.h
  74. 20 20
      Jolt/ObjectStream/ObjectStreamTextIn.cpp
  75. 5 3
      Jolt/ObjectStream/ObjectStreamTextIn.h
  76. 5 5
      Jolt/ObjectStream/ObjectStreamTextOut.cpp
  77. 3 1
      Jolt/ObjectStream/ObjectStreamTextOut.h
  78. 1 1
      Jolt/ObjectStream/ObjectStreamTypes.h
  79. 2 2
      Jolt/ObjectStream/SerializableAttribute.h
  80. 1 1
      Jolt/ObjectStream/TypeDeclarations.cpp
  81. 1 1
      Jolt/ObjectStream/TypeDeclarations.h
  82. 3 1
      Jolt/Physics/Body/Body.cpp
  83. 2 0
      Jolt/Physics/Body/Body.h
  84. 2 2
      Jolt/Physics/Body/BodyCreationSettings.h
  85. 1 1
      Jolt/Physics/Body/BodyFilter.h
  86. 2 0
      Jolt/Physics/Body/BodyID.h
  87. 3 1
      Jolt/Physics/Body/BodyManager.cpp
  88. 5 3
      Jolt/Physics/Body/BodyManager.h
  89. 2 0
      Jolt/Physics/Body/BodyPair.h
  90. 2 0
      Jolt/Physics/Body/MotionProperties.h
  91. 4 0
      Jolt/Physics/Character/Character.h
  92. 4 0
      Jolt/Physics/Character/CharacterBase.h
  93. 3 0
      Jolt/Physics/Character/CharacterVirtual.cpp
  94. 7 1
      Jolt/Physics/Character/CharacterVirtual.h
  95. 2 0
      Jolt/Physics/Collision/AABoxCast.h
  96. 1 1
      Jolt/Physics/Collision/BroadPhase/BroadPhaseBruteForce.cpp
  97. 3 1
      Jolt/Physics/Collision/BroadPhase/BroadPhaseBruteForce.h
  98. 4 0
      Jolt/Physics/Collision/BroadPhase/BroadPhaseQuadTree.h
  99. 3 3
      Jolt/Physics/Collision/BroadPhase/QuadTree.cpp
  100. 7 6
      Jolt/Physics/Collision/BroadPhase/QuadTree.h

+ 5 - 0
Build/README.md

@@ -24,6 +24,7 @@ There are a number of user configurable defines that turn on/off certain feature
 - JPH_EXTERNAL_PROFILE - Turns on the internal profiler but forwards the information to a user defined external system (see Profiler.h).
 - JPH_DEBUG_RENDERER - Adds support to draw lines and triangles, used to be able to debug draw the state of the world.
 - JPH_DISABLE_TEMP_ALLOCATOR - Disables the temporary memory allocator, used mainly to allow ASAN to do its job.
+- JPH_DISABLE_CUSTOM_ALLOCATOR - Disables the ability to override the memory allocator.
 - JPH_FLOATING_POINT_EXCEPTIONS_ENABLED - Turns on division by zero and invalid floating point exception support in order to detect bugs (Windows only).
 - JPH_USE_SSE4_1 - Enable SSE4.1 CPU instructions (x86/x64 only)
 - JPH_USE_SSE4_2 - Enable SSE4.2 CPU instructions (x86/x64 only)
@@ -38,6 +39,10 @@ There are a number of user configurable defines that turn on/off certain feature
 
 To override the default trace and assert mechanism install your own custom handlers in Trace and AssertFailed (see IssueReporting.h).
 
+## Custom Memory Allocator
+
+To implement your custom memory allocator override Allocate, Free, AlignedAllocate and AlignedFree (see Memory.h).
+
 ## Building
 
 ### Windows 10+ (CL - Default compiler)

+ 3 - 0
HelloWorld/HelloWorld.cpp

@@ -197,6 +197,9 @@ public:
 // Program entry point
 int main(int argc, char** argv)
 {
+	// Register allocation hook
+	RegisterDefaultAllocator();
+
 	// Install callbacks
 	Trace = TraceImpl;
 	JPH_IF_ENABLE_ASSERTS(AssertFailed = AssertFailedImpl;)

+ 1 - 1
Jolt/AABBTree/AABBTreeBuilder.cpp

@@ -84,7 +84,7 @@ float AABBTreeBuilder::Node::CalculateSAHCost(float inCostTraversal, float inCos
 	return surface_area > 0.0f? CalculateSAHCostInternal(inCostTraversal / surface_area, inCostLeaf / surface_area) : 0.0f;
 }
 
-void AABBTreeBuilder::Node::GetNChildren(uint inN, vector<const Node *> &outChildren) const
+void AABBTreeBuilder::Node::GetNChildren(uint inN, Array<const Node *> &outChildren) const
 {
 	JPH_ASSERT(outChildren.empty());
 

+ 3 - 1
Jolt/AABBTree/AABBTreeBuilder.h

@@ -38,6 +38,8 @@ public:
 	class Node : public NonCopyable
 	{
 	public:
+		JPH_OVERRIDE_NEW_DELETE
+
 		/// Constructor
 							Node();
 							~Node();
@@ -70,7 +72,7 @@ public:
 		float				CalculateSAHCost(float inCostTraversal, float inCostLeaf) const;
 
 		/// Recursively get children (breadth first) to get in total inN children (or less if there are no more)
-		void				GetNChildren(uint inN, vector<const Node *> &outChildren) const;
+		void				GetNChildren(uint inN, Array<const Node *> &outChildren) const;
 
 		/// Bounding box
 		AABox				mBounds;

+ 6 - 4
Jolt/AABBTree/AABBTreeToBuffer.h

@@ -13,6 +13,8 @@ JPH_SUPPRESS_WARNINGS_STD_END
 
 JPH_NAMESPACE_BEGIN
 
+template <class T> using Deque = deque<T, STLAllocator<T>>;
+
 /// Conversion algorithm that converts an AABB tree to an optimized binary buffer
 template <class TriangleCodec, class NodeCodec>
 class AABBTreeToBuffer
@@ -67,9 +69,9 @@ public:
 			uint *							mParentTrianglesStart = nullptr;			// Where to store mTriangleStart (to patch mChildTrianglesStart of my parent)
 		};
 		
-		deque<NodeData *> to_process;
-		deque<NodeData *> to_process_triangles;
-		vector<NodeData> node_list;
+		Deque<NodeData *> to_process;
+		Deque<NodeData *> to_process_triangles;
+		Array<NodeData> node_list;
 
 		node_list.reserve(node_count); // Needed to ensure that array is not reallocated, so we can keep pointers in the array
 		
@@ -81,7 +83,7 @@ public:
 		to_process.push_back(&node_list.back());
 
 		// Child nodes out of loop so we don't constantly realloc it
-		vector<const AABBTreeBuilder::Node *> child_nodes;
+		Array<const AABBTreeBuilder::Node *> child_nodes;
 		child_nodes.reserve(NumChildrenPerNode);
 
 		for (;;)

+ 1 - 1
Jolt/AABBTree/NodeCodec/NodeCodecQuadTreeHalfFloat.h

@@ -71,7 +71,7 @@ public:
 		/// Algorithm can enlarge the bounding boxes of the children during compression and returns these in outChildBoundsMin, outChildBoundsMax
 		/// inNodeBoundsMin, inNodeBoundsMax is the bounding box if inNode possibly widened by compressing the parent node
 		/// Returns uint(-1) on error and reports the error in outError
-		uint							NodeAllocate(const AABBTreeBuilder::Node *inNode, Vec3Arg inNodeBoundsMin, Vec3Arg inNodeBoundsMax, vector<const AABBTreeBuilder::Node *> &ioChildren, Vec3 outChildBoundsMin[NumChildrenPerNode], Vec3 outChildBoundsMax[NumChildrenPerNode], ByteBuffer &ioBuffer, const char *&outError) const
+		uint							NodeAllocate(const AABBTreeBuilder::Node *inNode, Vec3Arg inNodeBoundsMin, Vec3Arg inNodeBoundsMax, Array<const AABBTreeBuilder::Node *> &ioChildren, Vec3 outChildBoundsMin[NumChildrenPerNode], Vec3 outChildBoundsMax[NumChildrenPerNode], ByteBuffer &ioBuffer, const char *&outError) const
 		{
 			// We don't emit nodes for leafs
 			if (!inNode->HasChildren())

+ 3 - 7
Jolt/AABBTree/TriangleCodec/TriangleCodecIndexed8BitPackSOA4Flags.h

@@ -5,10 +5,6 @@
 
 #include <Jolt/Geometry/RayTriangle.h>
 
-JPH_SUPPRESS_WARNINGS_STD_BEGIN
-#include <unordered_map>
-JPH_SUPPRESS_WARNINGS_STD_END
-
 JPH_NAMESPACE_BEGIN
 
 /// Store vertices in 64 bits and indices in 8 bits + 8 bit of flags per triangle like this:
@@ -214,12 +210,12 @@ public:
 		}
 
 	private:
-		using VertexMap = vector<uint32>;
+		using VertexMap = Array<uint32>;
 
 		uint						mNumTriangles = 0;
-		vector<uint32>				mVertices;				///< Output vertices as an index into the original vertex list (inVertices), sorted according to occurrence
+		Array<uint32>				mVertices;				///< Output vertices as an index into the original vertex list (inVertices), sorted according to occurrence
 		VertexMap					mVertexMap;				///< Maps from the original mesh vertex index (inVertices) to the index in our output vertices (mVertices)
-		vector<uint>				mOffsetsToPatch;		///< Offsets to the vertex buffer that need to be patched in once all nodes have been packed
+		Array<uint>					mOffsetsToPatch;		///< Offsets to the vertex buffer that need to be patched in once all nodes have been packed
 	};
 
 	/// This class is used to decode and decompress triangle data packed by the EncodingContext

+ 2 - 2
Jolt/Core/ByteBuffer.h

@@ -40,7 +40,7 @@ public:
 
 		// Construct elements
 		for (Type *d = data, *d_end = data + inSize; d < d_end; ++d)
-			new (d) Type;
+			::new (d) Type;
 
 		// Return pointer
 		return data;
@@ -48,7 +48,7 @@ public:
 
 	/// Append inData to the buffer
 	template <class Type>
-	void			AppendVector(const vector<Type> &inData)
+	void			AppendVector(const Array<Type> &inData)
 	{
 		size_t size = inData.size() * sizeof(Type);
 		uint8 *data = Allocate<uint8>(size);

+ 2 - 2
Jolt/Core/Factory.cpp

@@ -74,9 +74,9 @@ void Factory::Clear()
 	mClassHashMap.clear();
 }
 
-vector<const RTTI *> Factory::GetAllClasses() const
+Array<const RTTI *> Factory::GetAllClasses() const
 {
-	vector<const RTTI *> all_classes;
+	Array<const RTTI *> all_classes;
 	all_classes.reserve(mClassNameMap.size());
 	for (const ClassNameMap::value_type &c : mClassNameMap)
 		all_classes.push_back(c.second);

+ 6 - 7
Jolt/Core/Factory.h

@@ -4,10 +4,7 @@
 #pragma once
 
 #include <Jolt/Core/RTTI.h>
-
-JPH_SUPPRESS_WARNINGS_STD_BEGIN
-#include <unordered_map>
-JPH_SUPPRESS_WARNINGS_STD_END
+#include <Jolt/Core/UnorderedMap.h>
 
 JPH_NAMESPACE_BEGIN
 
@@ -15,6 +12,8 @@ JPH_NAMESPACE_BEGIN
 class Factory
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Create an object
 	void *						CreateObject(const char *inName);
 
@@ -34,15 +33,15 @@ public:
 	void						Clear();
 
 	/// Get all registered classes
-	vector<const RTTI *>		GetAllClasses() const;
+	Array<const RTTI *>			GetAllClasses() const;
 
 	/// Singleton factory instance
 	static Factory *			sInstance;
 
 private:
-	using ClassNameMap = unordered_map<string_view, const RTTI *>;
+	using ClassNameMap = UnorderedMap<string_view, const RTTI *>;
 
-	using ClassHashMap = unordered_map<uint32, const RTTI *>;
+	using ClassHashMap = UnorderedMap<uint32, const RTTI *>;
 
 	/// Map of class names to type info
 	ClassNameMap				mClassNameMap;

+ 5 - 10
Jolt/Core/FixedSizeFreeList.h

@@ -5,7 +5,6 @@
 
 #include <Jolt/Core/NonCopyable.h>
 #include <Jolt/Core/Mutex.h>
-#include <Jolt/Core/Memory.h>
 
 JPH_SUPPRESS_WARNINGS_STD_BEGIN
 #include <atomic>
@@ -21,14 +20,10 @@ class FixedSizeFreeList : public NonCopyable
 {
 private:
 	/// Storage type for an Object
-	struct alignas(Object) ObjectStorage
+	struct ObjectStorage
 	{
-		/// Constructor to satisfy the vector class
-							ObjectStorage() = default;
-							ObjectStorage(const ObjectStorage &inRHS) : mNextFreeObject(inRHS.mNextFreeObject.load()) { memcpy(mData, inRHS.mData, sizeof(Object)); }
-
-		/// Storage space for the Object, stored as uninitialized data
-		uint8				mData[sizeof(Object)];
+		/// The object we're storing
+		Object				mObject;
 
 		/// When the object is freed (or in the process of being freed as a batch) this will contain the next free object
 		/// When an object is in use it will contain the object's index in the free list
@@ -116,10 +111,10 @@ public:
 	inline void				DestructObjectBatch(Batch &ioBatch);
 
 	/// Access an object by index.
-	inline Object &			Get(uint32 inObjectIndex)				{ return reinterpret_cast<Object &>(GetStorage(inObjectIndex).mData); }
+	inline Object &			Get(uint32 inObjectIndex)				{ return GetStorage(inObjectIndex).mObject; }
 
 	/// Access an object by index.
-	inline const Object &	Get(uint32 inObjectIndex) const			{ return reinterpret_cast<const Object &>(GetStorage(inObjectIndex).mData); }
+	inline const Object &	Get(uint32 inObjectIndex) const			{ return GetStorage(inObjectIndex).mObject; }
 };
 
 JPH_NAMESPACE_END

+ 7 - 7
Jolt/Core/FixedSizeFreeList.inl

@@ -13,7 +13,7 @@ FixedSizeFreeList<Object>::~FixedSizeFreeList()
 	uint32 num_pages = mNumObjectsAllocated / mPageSize;
 	for (uint32 page = 0; page < num_pages; ++page)
 		AlignedFree(mPages[page]);
-	delete [] mPages;
+	Free(mPages);
 }
 
 template <typename Object>
@@ -31,7 +31,7 @@ void FixedSizeFreeList<Object>::Init(uint inMaxObjects, uint inPageSize)
 	JPH_IF_ENABLE_ASSERTS(mNumFreeObjects = mNumPages * inPageSize;)
 
 	// Allocate page table
-	mPages = new ObjectStorage * [mNumPages];
+	mPages = reinterpret_cast<ObjectStorage **>(Allocate(mNumPages * sizeof(ObjectStorage *)));
 
 	// We didn't yet use any objects of any page
 	mNumObjectsAllocated = 0;
@@ -66,7 +66,7 @@ uint32 FixedSizeFreeList<Object>::ConstructObject(Parameters &&... inParameters)
 					uint32 next_page = mNumObjectsAllocated / mPageSize;
 					if (next_page == mNumPages)
 						return cInvalidObjectIndex; // Out of space!
-					mPages[next_page] = reinterpret_cast<ObjectStorage *>(AlignedAlloc(mPageSize * sizeof(ObjectStorage), JPH_CACHE_LINE_SIZE));
+					mPages[next_page] = reinterpret_cast<ObjectStorage *>(AlignedAllocate(mPageSize * sizeof(ObjectStorage), max<size_t>(alignof(ObjectStorage), JPH_CACHE_LINE_SIZE)));
 					mNumObjectsAllocated += mPageSize;
 				}
 			}
@@ -74,7 +74,7 @@ uint32 FixedSizeFreeList<Object>::ConstructObject(Parameters &&... inParameters)
 			// Allocation successful
 			JPH_IF_ENABLE_ASSERTS(mNumFreeObjects.fetch_sub(1, memory_order_relaxed);)
 			ObjectStorage &storage = GetStorage(first_free);
-			new (&storage.mData) Object(forward<Parameters>(inParameters)...);
+			::new (&storage.mObject) Object(forward<Parameters>(inParameters)...);
 			storage.mNextFreeObject.store(first_free, memory_order_release);
 			return first_free;
 		}
@@ -92,7 +92,7 @@ uint32 FixedSizeFreeList<Object>::ConstructObject(Parameters &&... inParameters)
 				// Allocation successful
 				JPH_IF_ENABLE_ASSERTS(mNumFreeObjects.fetch_sub(1, memory_order_relaxed);)
 				ObjectStorage &storage = GetStorage(first_free);
-				new (&storage.mData) Object(forward<Parameters>(inParameters)...);
+				::new (&storage.mObject) Object(forward<Parameters>(inParameters)...);
 				storage.mNextFreeObject.store(first_free, memory_order_release);
 				return first_free;
 			}
@@ -127,7 +127,7 @@ void FixedSizeFreeList<Object>::DestructObjectBatch(Batch &ioBatch)
 			do
 			{
 				ObjectStorage &storage = GetStorage(object_idx);
-				reinterpret_cast<Object &>(storage.mData).~Object();
+				storage.mObject.~Object();
 				object_idx = storage.mNextFreeObject.load(memory_order_relaxed);
 			}
 			while (object_idx != cInvalidObjectIndex);
@@ -170,7 +170,7 @@ void FixedSizeFreeList<Object>::DestructObject(uint32 inObjectIndex)
 
 	// Call destructor
 	ObjectStorage &storage = GetStorage(inObjectIndex); 
-	reinterpret_cast<Object &>(storage.mData).~Object();
+	storage.mObject.~Object();
 
 	// Add to object free list
 	for (;;)

+ 6 - 0
Jolt/Core/JobSystem.h

@@ -47,6 +47,8 @@ protected:
 	class Job;
 
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// A job handle contains a reference to a job. The job will be deleted as soon as there are no JobHandles.
 	/// referring to the job and when it is not in the job queue / being processed.
 	class JobHandle : private Ref<Job>
@@ -95,6 +97,8 @@ public:
 	class Barrier : public NonCopyable
 	{
 	public:
+		JPH_OVERRIDE_NEW_DELETE
+
 		/// Add a job to this barrier
 		/// Note that jobs can keep being added to the barrier while waiting for the barrier
 		virtual void		AddJob(const JobHandle &inJob) = 0;
@@ -141,6 +145,8 @@ protected:
 	class Job
 	{
 	public:
+		JPH_OVERRIDE_NEW_DELETE
+
 		/// Constructor
 							Job([[maybe_unused]] const char *inJobName, [[maybe_unused]] ColorArg inColor, JobSystem *inJobSystem, const JobFunction &inJobFunction, uint32 inNumDependencies) : 
 		#if defined(JPH_EXTERNAL_PROFILE) || defined(JPH_PROFILE_ENABLED)

+ 10 - 13
Jolt/Core/JobSystemThreadPool.cpp

@@ -266,7 +266,7 @@ void JobSystemThreadPool::StartThreads(int inNumThreads)
 	mQuit = false;
 
 	// Allocate heads
-	mHeads = new atomic<uint> [inNumThreads];
+	mHeads = reinterpret_cast<atomic<uint> *>(Allocate(sizeof(atomic<uint>) * inNumThreads));
 	for (int i = 0; i < inNumThreads; ++i)
 		mHeads[i] = 0;
 
@@ -274,14 +274,7 @@ void JobSystemThreadPool::StartThreads(int inNumThreads)
 	JPH_ASSERT(mThreads.empty());
 	mThreads.reserve(inNumThreads);
 	for (int i = 0; i < inNumThreads; ++i)
-	{
-		// Name the thread
-		char name[64];
-		snprintf(name, sizeof(name), "Worker %d", int(i + 1));
-
-		// Create thread
-		mThreads.emplace_back([this, name, i] { ThreadMain(name, i); });
-	}
+		mThreads.emplace_back([this, i] { ThreadMain(i); });
 }
 
 JobSystemThreadPool::~JobSystemThreadPool()
@@ -328,7 +321,7 @@ void JobSystemThreadPool::StopThreads()
 	}
 
 	// Destroy heads and reset tail
-	delete [] mHeads;
+	Free(mHeads);
 	mHeads = nullptr;
 	mTail = 0;
 }
@@ -523,17 +516,21 @@ static void SetThreadName(const char *inName)
 
 #endif
 
-void JobSystemThreadPool::ThreadMain([[maybe_unused]] const char *inName, int inThreadIndex)
+void JobSystemThreadPool::ThreadMain(int inThreadIndex)
 {
+	// Name the thread
+	char name[64];
+	snprintf(name, sizeof(name), "Worker %d", int(inThreadIndex + 1));
+
 #ifdef JPH_PLATFORM_WINDOWS
-	SetThreadName(inName);
+	SetThreadName(name);
 #endif
 
 	// Enable floating point exceptions
 	FPExceptionsEnable enable_exceptions;
 	JPH_UNUSED(enable_exceptions);
 
-	JPH_PROFILE_THREAD_START(inName);
+	JPH_PROFILE_THREAD_START(name);
 
 	atomic<uint> &head = mHeads[inThreadIndex];
 

+ 6 - 2
Jolt/Core/JobSystemThreadPool.h

@@ -22,6 +22,8 @@ JPH_NAMESPACE_BEGIN
 class JobSystemThreadPool final : public JobSystem
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Creates a thread pool.
 	/// @see JobSystemThreadPool::Init
 							JobSystemThreadPool(uint inMaxJobs, uint inMaxBarriers, int inNumThreads = -1);
@@ -84,6 +86,8 @@ private:
 	class BarrierImpl : public Barrier
 	{
 	public:
+		JPH_OVERRIDE_NEW_DELETE
+
 		/// Constructor
 							BarrierImpl();
 		virtual				~BarrierImpl() override;
@@ -120,7 +124,7 @@ private:
 	void					StopThreads();
 	
 	/// Entry point for a thread
-	void					ThreadMain(const char *inName, int inThreadIndex);
+	void					ThreadMain(int inThreadIndex);
 
 	/// Get the head of the thread that has processed the least amount of jobs
 	inline uint				GetHead() const;
@@ -137,7 +141,7 @@ private:
 	BarrierImpl *			mBarriers = nullptr;							///< List of the actual barriers
 
 	/// Threads running jobs
-	vector<thread>			mThreads;
+	Array<thread>			mThreads;
 
 	// The job queue
 	static constexpr uint32 cQueueLength = 1024;

+ 1 - 1
Jolt/Core/LinearCurve.h

@@ -58,7 +58,7 @@ public:
 	void				RestoreBinaryState(StreamIn &inStream);
 
 	/// The points on the curve, should be sorted ascending by x
-	using Points = vector<Point>;
+	using Points = Array<Point>;
 	Points				mPoints;
 };
 

+ 1 - 2
Jolt/Core/LockFreeHashMap.h

@@ -3,7 +3,6 @@
 
 #pragma once
 
-#include <Jolt/Core/Memory.h>
 #include <Jolt/Core/NonCopyable.h>
 
 JPH_SUPPRESS_WARNINGS_STD_BEGIN
@@ -137,7 +136,7 @@ public:
 #endif // JPH_ENABLE_ASSERTS
 
 	/// Get all key/value pairs
-	inline void				GetAllKeyValues(vector<const KeyValue *> &outAll) const;
+	inline void				GetAllKeyValues(Array<const KeyValue *> &outAll) const;
 
 	/// Non-const iterator
 	struct Iterator

+ 4 - 4
Jolt/Core/LockFreeHashMap.inl

@@ -11,7 +11,7 @@ JPH_NAMESPACE_BEGIN
 
 inline LFHMAllocator::~LFHMAllocator()
 {
-	delete [] mObjectStore;
+	Free(mObjectStore);
 }
 
 inline void LFHMAllocator::Init(uint inObjectStoreSizeBytes)
@@ -19,7 +19,7 @@ inline void LFHMAllocator::Init(uint inObjectStoreSizeBytes)
 	JPH_ASSERT(mObjectStore == nullptr);
 
 	mObjectStoreSizeBytes = inObjectStoreSizeBytes;
-	mObjectStore = new uint8 [inObjectStoreSizeBytes];
+	mObjectStore = reinterpret_cast<uint8 *>(JPH::Allocate(inObjectStoreSizeBytes));
 }
 
 inline void LFHMAllocator::Clear()
@@ -114,7 +114,7 @@ void LockFreeHashMap<Key, Value>::Init(uint32 inMaxBuckets)
 	mNumBuckets = inMaxBuckets;
 	mMaxBuckets = inMaxBuckets;
 
-	mBuckets = reinterpret_cast<atomic<uint32> *>(AlignedAlloc(inMaxBuckets * sizeof(atomic<uint32>), 16));
+	mBuckets = reinterpret_cast<atomic<uint32> *>(AlignedAllocate(inMaxBuckets * sizeof(atomic<uint32>), 16));
 
 	Clear();
 }
@@ -231,7 +231,7 @@ inline const typename LockFreeHashMap<Key, Value>::KeyValue *LockFreeHashMap<Key
 }
 
 template <class Key, class Value>
-inline void LockFreeHashMap<Key, Value>::GetAllKeyValues(vector<const KeyValue *> &outAll) const
+inline void LockFreeHashMap<Key, Value>::GetAllKeyValues(Array<const KeyValue *> &outAll) const
 {
 	for (const atomic<uint32> *bucket = mBuckets; bucket < mBuckets + mNumBuckets; ++bucket)
 	{

+ 37 - 4
Jolt/Core/Memory.cpp

@@ -3,8 +3,6 @@
 
 #include <Jolt/Jolt.h>
 
-#include <Jolt/Core/Memory.h>
-
 JPH_SUPPRESS_WARNINGS_STD_BEGIN
 #include <cstdlib>
 JPH_SUPPRESS_WARNINGS_STD_END
@@ -12,7 +10,25 @@ JPH_SUPPRESS_WARNINGS_STD_END
 
 JPH_NAMESPACE_BEGIN
 
-void *AlignedAlloc(size_t inSize, size_t inAlignment)
+#ifdef JPH_DISABLE_CUSTOM_ALLOCATOR
+	#define JPH_ALLOC_FN(x)	x
+	#define JPH_ALLOC_SCOPE
+#else
+	#define JPH_ALLOC_FN(x)	x##Impl
+	#define JPH_ALLOC_SCOPE static
+#endif
+
+JPH_ALLOC_SCOPE void *JPH_ALLOC_FN(Allocate)(size_t inSize)
+{
+	return malloc(inSize);
+}
+
+JPH_ALLOC_SCOPE void JPH_ALLOC_FN(Free)(void *inBlock)
+{
+	free(inBlock);
+}
+
+JPH_ALLOC_SCOPE void *JPH_ALLOC_FN(AlignedAllocate)(size_t inSize, size_t inAlignment)
 {
 #if defined(JPH_PLATFORM_WINDOWS)
 	// Microsoft doesn't implement C++17 std::aligned_alloc
@@ -24,7 +40,7 @@ void *AlignedAlloc(size_t inSize, size_t inAlignment)
 #endif
 }
 
-void AlignedFree(void *inBlock)
+JPH_ALLOC_SCOPE void JPH_ALLOC_FN(AlignedFree)(void *inBlock)
 {
 #if defined(JPH_PLATFORM_WINDOWS)
 	_aligned_free(inBlock);
@@ -35,4 +51,21 @@ void AlignedFree(void *inBlock)
 #endif
 }
 
+#ifndef JPH_DISABLE_CUSTOM_ALLOCATOR
+
+AllocateFunction Allocate = nullptr;
+FreeFunction Free = nullptr;
+AlignedAllocateFunction AlignedAllocate = nullptr;
+AlignedFreeFunction AlignedFree = nullptr;
+
+void RegisterDefaultAllocator()
+{
+	Allocate = AllocateImpl;
+	Free = FreeImpl;
+	AlignedAllocate = AlignedAllocateImpl;
+	AlignedFree = AlignedFreeImpl;
+}
+
+#endif // JPH_DISABLE_CUSTOM_ALLOCATOR
+
 JPH_NAMESPACE_END

+ 43 - 3
Jolt/Core/Memory.h

@@ -5,10 +5,50 @@
 
 JPH_NAMESPACE_BEGIN
 
-/// Allocate a block of memory aligned to inAlignment bytes of size inSize
-void *AlignedAlloc(size_t inSize, size_t inAlignment);
+#ifndef JPH_DISABLE_CUSTOM_ALLOCATOR
 
-/// Free memory block allocated with AlignedAlloc
+// Normal memory allocation, must be at least 8 byte aligned on 32 bit platform and 16 byte aligned on 64 bit platform
+using AllocateFunction = void *(*)(size_t inSize);
+using FreeFunction = void (*)(void *inBlock);
+
+// Aligned memory allocation
+using AlignedAllocateFunction = void *(*)(size_t inSize, size_t inAlignment);
+using AlignedFreeFunction = void (*)(void *inBlock);
+
+// User defined allocation / free functions
+extern AllocateFunction Allocate;
+extern FreeFunction Free;
+extern AlignedAllocateFunction AlignedAllocate;
+extern AlignedFreeFunction AlignedFree;
+
+/// Register platform default allocation / free functions
+void RegisterDefaultAllocator();
+
+/// Macro to override the new and delete functions
+#define JPH_OVERRIDE_NEW_DELETE \
+	JPH_INLINE void *operator new (size_t inCount)											{ return JPH::Allocate(inCount); } \
+	JPH_INLINE void operator delete (void *inPointer) noexcept								{ JPH::Free(inPointer); } \
+	JPH_INLINE void *operator new[] (size_t inCount)										{ return JPH::Allocate(inCount); } \
+	JPH_INLINE void operator delete[] (void *inPointer) noexcept							{ JPH::Free(inPointer); } \
+	JPH_INLINE void *operator new (size_t inCount, align_val_t inAlignment)					{ return JPH::AlignedAllocate(inCount, static_cast<size_t>(inAlignment)); } \
+	JPH_INLINE void operator delete (void *inPointer, align_val_t inAlignment) noexcept		{ JPH::AlignedFree(inPointer); } \
+	JPH_INLINE void *operator new[] (size_t inCount, align_val_t inAlignment)				{ return JPH::AlignedAllocate(inCount, static_cast<size_t>(inAlignment)); } \
+	JPH_INLINE void operator delete[] (void *inPointer, align_val_t inAlignment) noexcept	{ JPH::AlignedFree(inPointer); }
+
+#else
+
+// Directly define the allocation functions
+void *Allocate(size_t inSize);
+void Free(void *inBlock);
+void *AlignedAllocate(size_t inSize, size_t inAlignment);
 void AlignedFree(void *inBlock);
 
+// Don't implement allocator registering
+inline void RegisterDefaultAllocator() { }
+
+// Don't override new/delete
+#define JPH_OVERRIDE_NEW_DELETE
+
+#endif // !JPH_DISABLE_CUSTOM_ALLOCATOR
+
 JPH_NAMESPACE_END

+ 2 - 0
Jolt/Core/MutexArray.h

@@ -84,6 +84,8 @@ private:
 	/// Align the mutex to a cache line to ensure there is no false sharing (this is platform dependent, we do this to be safe)
 	struct alignas(JPH_CACHE_LINE_SIZE) MutexStorage
 	{
+		JPH_OVERRIDE_NEW_DELETE
+
 		MutexType			mMutex;
 	};
 

+ 6 - 6
Jolt/Core/Profiler.cpp

@@ -19,7 +19,7 @@ JPH_NAMESPACE_BEGIN
 // Profiler
 //////////////////////////////////////////////////////////////////////////////////////////
 
-Profiler Profiler::sInstance;
+Profiler *Profiler::sInstance = nullptr;
 thread_local ProfileThread *ProfileThread::sInstance = nullptr;
 
 bool ProfileMeasurement::sOutOfSamplesReported = false;
@@ -55,7 +55,7 @@ void Profiler::RemoveThread(ProfileThread *inThread)
 { 
 	lock_guard lock(mLock); 
 	
-	vector<ProfileThread *>::iterator i = find(mThreads.begin(), mThreads.end(), inThread); 
+	Array<ProfileThread *>::iterator i = find(mThreads.begin(), mThreads.end(), inThread); 
 	JPH_ASSERT(i != mThreads.end()); 
 	mThreads.erase(i); 
 }
@@ -138,7 +138,7 @@ void Profiler::DumpInternal()
 		}
 
 	// Determine tag of this profile
-	string tag;
+	String tag;
 	if (mDumpTag.empty())
 	{
 		// Next sequence number
@@ -167,9 +167,9 @@ void Profiler::DumpInternal()
 	DumpChart(tag.c_str(), threads, key_to_aggregators, aggregators);
 }
 
-static string sHTMLEncode(const char *inString)
+static String sHTMLEncode(const char *inString)
 {
-	string str(inString);
+	String str(inString);
 	StringReplace(str, "<", "&lt;");
 	StringReplace(str, ">", "&gt;");
 	return str;
@@ -345,7 +345,7 @@ void Profiler::DumpChart(const char *inTag, const Threads &inThreads, const KeyT
 		if (!first)
 			f << ",";
 		first = false;
-		string name = "\"" + sHTMLEncode(a.mName) + "\"";
+		String name = "\"" + sHTMLEncode(a.mName) + "\"";
 		f << name;
 	}
 	f << "],\ncalls: [";

+ 26 - 12
Jolt/Core/Profiler.h

@@ -5,11 +5,11 @@
 
 JPH_SUPPRESS_WARNINGS_STD_BEGIN
 #include <mutex>
-#include <unordered_map>
 JPH_SUPPRESS_WARNINGS_STD_END
 
 #include <Jolt/Core/NonCopyable.h>
 #include <Jolt/Core/TickCounter.h>
+#include <Jolt/Core/UnorderedMap.h>
 
 #if defined(JPH_EXTERNAL_PROFILE)
 
@@ -76,6 +76,8 @@ class ProfileThread;
 class Profiler : public NonCopyable
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Increments the frame counter to provide statistics per frame
 	void						NextFrame();
 
@@ -90,13 +92,13 @@ public:
 	void						RemoveThread(ProfileThread *inThread);
 
 	/// Singleton instance
-	static Profiler				sInstance;
+	static Profiler *			sInstance;
 								
 private:
 	/// Helper class to freeze ProfileSamples per thread while processing them
 	struct ThreadSamples
 	{
-		string					mThreadName;
+		String					mThreadName;
 		ProfileSample *			mSamplesBegin;
 		ProfileSample *			mSamplesEnd;
 	};
@@ -135,9 +137,9 @@ private:
 		uint64					mMaxCyclesInCallWithChildren = 0;									///< Maximum amount of cycles spent per call
 	};							
 
-	using Threads = vector<ThreadSamples>;
-	using Aggregators = vector<Aggregator>;
-	using KeyToAggregator = unordered_map<const char *, size_t>;
+	using Threads = Array<ThreadSamples>;
+	using Aggregators = Array<Aggregator>;
+	using KeyToAggregator = UnorderedMap<const char *, size_t>;
 
 	/// Helper function to aggregate profile sample data
 	static void					sAggregate(int inDepth, uint32 inColor, ProfileSample *&ioSample, const ProfileSample *inEnd, Aggregators &ioAggregators, KeyToAggregator &ioKeyToAggregator);
@@ -148,15 +150,17 @@ private:
 	void						DumpChart(const char *inTag, const Threads &inThreads, const KeyToAggregator &inKeyToAggregators, const Aggregators &inAggregators);
 
 	mutex						mLock;																///< Lock that protects mThreads
-	vector<ProfileThread *>		mThreads;															///< List of all active threads
+	Array<ProfileThread *>		mThreads;															///< List of all active threads
 	bool						mDump = false;														///< When true, the samples are dumped next frame
-	string						mDumpTag;															///< When not empty, this overrides the auto incrementing number of the dump filename
+	String						mDumpTag;															///< When not empty, this overrides the auto incrementing number of the dump filename
 };							
 
 // Class that contains the information of a single scoped measurement
 class alignas(16) ProfileSample : public NonCopyable
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	const char *				mName;																///< User defined name of this item
 	uint32						mColor;																///< Color to use for this sample
 	uint8						mDepth;																///< Calculated depth
@@ -169,13 +173,15 @@ public:
 class ProfileThread : public NonCopyable
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Constructor
 	inline						ProfileThread(const string_view &inThreadName);
 	inline						~ProfileThread();
 
 	static const uint cMaxSamples = 65536;
 
-	string						mThreadName;														///< Name of the thread that we're collecting information for
+	String						mThreadName;														///< Name of the thread that we're collecting information for
 	ProfileSample				mSamples[cMaxSamples];												///< Buffer of samples
 	uint						mCurrentSample = 0;													///< Next position to write a sample to
 
@@ -208,8 +214,14 @@ JPH_NAMESPACE_END
 JPH_SUPPRESS_WARNING_PUSH
 JPH_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic")
 
+/// Start instrumenting program
+#define JPH_PROFILE_START(name)			do { Profiler::sInstance = new Profiler; JPH_PROFILE_THREAD_START(name); } while (false)
+
+/// End instrumenting program
+#define JPH_PROFILE_END()				do { JPH_PROFILE_THREAD_END(); delete Profiler::sInstance; Profiler::sInstance = nullptr; } while (false)
+
 /// Start instrumenting a thread
-#define JPH_PROFILE_THREAD_START(name)	ProfileThread::sInstance = new ProfileThread(name)
+#define JPH_PROFILE_THREAD_START(name)	do { if (Profiler::sInstance) ProfileThread::sInstance = new ProfileThread(name); } while (false)
 
 /// End instrumenting a thread
 #define JPH_PROFILE_THREAD_END()		do { delete ProfileThread::sInstance; ProfileThread::sInstance = nullptr; } while (false)
@@ -223,10 +235,10 @@ JPH_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic")
 #define JPH_PROFILE_FUNCTION()			JPH_PROFILE(JPH_FUNCTION_NAME)
 								
 /// Update frame counter								
-#define JPH_PROFILE_NEXTFRAME()			Profiler::sInstance.NextFrame()
+#define JPH_PROFILE_NEXTFRAME()			Profiler::sInstance->NextFrame()
 
 /// Dump profiling info
-#define JPH_PROFILE_DUMP(...)			Profiler::sInstance.Dump(__VA_ARGS__)
+#define JPH_PROFILE_DUMP(...)			Profiler::sInstance->Dump(__VA_ARGS__)
 
 JPH_SUPPRESS_WARNING_POP
 
@@ -239,6 +251,8 @@ JPH_SUPPRESS_WARNING_POP
 JPH_SUPPRESS_WARNING_PUSH
 JPH_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic")
 
+#define JPH_PROFILE_START(name)
+#define JPH_PROFILE_END()
 #define JPH_PROFILE_THREAD_START(name)
 #define JPH_PROFILE_THREAD_END()
 #define JPH_PROFILE(...)

+ 2 - 2
Jolt/Core/Profiler.inl

@@ -10,12 +10,12 @@ JPH_NAMESPACE_BEGIN
 ProfileThread::ProfileThread(const string_view &inThreadName) :
 	mThreadName(inThreadName)
 {
-	Profiler::sInstance.AddThread(this);
+	Profiler::sInstance->AddThread(this);
 }
 
 ProfileThread::~ProfileThread()
 {
-	Profiler::sInstance.RemoveThread(this);
+	Profiler::sInstance->RemoveThread(this);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////

+ 2 - 0
Jolt/Core/RTTI.h

@@ -189,6 +189,7 @@ protected:
 // JPH_DECLARE_RTTI_NON_VIRTUAL
 #define JPH_DECLARE_RTTI_NON_VIRTUAL(class_name)																	\
 public:																												\
+	JPH_OVERRIDE_NEW_DELETE																							\
 	friend RTTI *				GetRTTIOfType(class_name *);														\
 	friend inline const RTTI *	GetRTTI(const class_name *inObject) { return GetRTTIOfType((class_name *)nullptr); }\
 	static void					sCreateRTTI(RTTI &inRTTI);															\
@@ -228,6 +229,7 @@ public:																												\
 
 #define JPH_DECLARE_RTTI_HELPER(class_name, modifier)																\
 public:																												\
+	JPH_OVERRIDE_NEW_DELETE																							\
 	friend RTTI *				GetRTTIOfType(class_name *);														\
 	friend inline const RTTI *	GetRTTI(const class_name *inObject) { return inObject->GetRTTI(); }					\
 	virtual const RTTI *		GetRTTI() const modifier;															\

+ 1 - 1
Jolt/Core/Reference.h

@@ -43,7 +43,7 @@ public:
 	/// Mark this class as embedded, this means the type can be used in a compound or constructed on the stack.
 	/// The Release function will never destruct the object, it is assumed the destructor will be called by whoever allocated
 	/// the object and at that point in time it is checked that no references are left to the structure.
-	inline void				SetEmbedded()									{ JPH_IF_ENABLE_ASSERTS(uint32 old = ) mRefCount.fetch_add(cEmbedded, memory_order_relaxed); JPH_ASSERT(old < cEmbedded); }
+	inline void				SetEmbedded() const								{ JPH_IF_ENABLE_ASSERTS(uint32 old = ) mRefCount.fetch_add(cEmbedded, memory_order_relaxed); JPH_ASSERT(old < cEmbedded); }
 
 	/// Assignment operator
 	inline RefTarget &		operator = (const RefTarget &)					{ /* Don't copy refcount */ return *this; }

+ 16 - 16
Jolt/Core/Result.h

@@ -20,11 +20,11 @@ public:
 		switch (inRHS.mState)
 		{
 		case EState::Valid:
-			new (&mResult) Type (inRHS.mResult);
+			::new (&mResult) Type (inRHS.mResult);
 			break;
 
 		case EState::Error:
-			new (&mError) string(inRHS.mError);
+			::new (&mError) String(inRHS.mError);
 			break;
 
 		case EState::Invalid:
@@ -39,11 +39,11 @@ public:
 		switch (inRHS.mState)
 		{
 		case EState::Valid:
-			new (&mResult) Type (move(inRHS.mResult));
+			::new (&mResult) Type (move(inRHS.mResult));
 			break;
 
 		case EState::Error:
-			new (&mError) string(move(inRHS.mError));
+			::new (&mError) String(move(inRHS.mError));
 			break;
 
 		case EState::Invalid:
@@ -66,11 +66,11 @@ public:
 		switch (inRHS.mState)
 		{
 		case EState::Valid:
-			new (&mResult) Type (inRHS.mResult);
+			::new (&mResult) Type (inRHS.mResult);
 			break;
 
 		case EState::Error:
-			new (&mError) string(inRHS.mError);
+			::new (&mError) String(inRHS.mError);
 			break;
 
 		case EState::Invalid:
@@ -90,11 +90,11 @@ public:
 		switch (inRHS.mState)
 		{
 		case EState::Valid:
-			new (&mResult) Type (move(inRHS.mResult));
+			::new (&mResult) Type (move(inRHS.mResult));
 			break;
 
 		case EState::Error:
-			new (&mError) string(move(inRHS.mError));
+			::new (&mError) String(move(inRHS.mError));
 			break;
 
 		case EState::Invalid:
@@ -116,7 +116,7 @@ public:
 			break; 
 
 		case EState::Error:
-			mError.~string();
+			mError.~String();
 			break;
 
 		case EState::Invalid:
@@ -136,27 +136,27 @@ public:
 	const Type &		Get() const									{ JPH_ASSERT(IsValid()); return mResult; }
 
 	/// Set the result value
-	void				Set(const Type &inResult)					{ Clear(); new (&mResult) Type(inResult); mState = EState::Valid; }
+	void				Set(const Type &inResult)					{ Clear(); ::new (&mResult) Type(inResult); mState = EState::Valid; }
 
 	/// Set the result value (move value)
-	void				Set(const Type &&inResult)					{ Clear(); new (&mResult) Type(move(inResult)); mState = EState::Valid; }
+	void				Set(const Type &&inResult)					{ Clear(); ::new (&mResult) Type(move(inResult)); mState = EState::Valid; }
 
 	/// Check if we had an error
 	bool				HasError() const							{ return mState == EState::Error; }
 
 	/// Get the error value
-	const string &		GetError() const							{ JPH_ASSERT(HasError()); return mError; }
+	const String &		GetError() const							{ JPH_ASSERT(HasError()); return mError; }
 
 	/// Set an error value
-	void				SetError(const char *inError)				{ Clear(); new (&mError) string(inError); mState = EState::Error; }
-	void				SetError(const string_view &inError)		{ Clear(); new (&mError) string(inError); mState = EState::Error; }
-	void				SetError(string &&inError)					{ Clear(); new (&mError) string(move(inError)); mState = EState::Error; }
+	void				SetError(const char *inError)				{ Clear(); ::new (&mError) String(inError); mState = EState::Error; }
+	void				SetError(const string_view &inError)		{ Clear(); ::new (&mError) String(inError); mState = EState::Error; }
+	void				SetError(String &&inError)					{ Clear(); ::new (&mError) String(move(inError)); mState = EState::Error; }
 
 private:
 	union
 	{
 		Type			mResult;									///< The actual result object
-		string			mError;										///< The error description if the result failed
+		String			mError;										///< The error description if the result failed
 	};
 
 	/// State of the result

+ 1 - 3
Jolt/Core/STLAlignedAllocator.h

@@ -3,8 +3,6 @@
 
 #pragma once
 
-#include <Jolt/Core/Memory.h>
-
 JPH_NAMESPACE_BEGIN
 
 /// STL allocator that takes care that memory is aligned to N bytes
@@ -36,7 +34,7 @@ public:
 	/// Allocate memory
 	inline pointer			allocate(size_type inN)
 	{
-		return (pointer)AlignedAlloc(inN * sizeof(value_type), N);
+		return (pointer)AlignedAllocate(inN * sizeof(value_type), N);
 	}
 
 	/// Free memory

+ 101 - 0
Jolt/Core/STLAllocator.h

@@ -0,0 +1,101 @@
+// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
+// SPDX-License-Identifier: MIT
+
+#pragma once
+
+JPH_NAMESPACE_BEGIN
+
+#ifndef JPH_DISABLE_CUSTOM_ALLOCATOR
+
+/// STL allocator that forwards to our allocation functions
+template <typename T>
+class STLAllocator
+{
+public:
+	using value_type = T;
+
+	/// Pointer to type
+	using pointer = T *;
+	using const_pointer = const T *;
+
+	/// Reference to type.
+	/// Can be removed in C++20.
+	using reference = T &;
+	using const_reference = const T &;
+
+	using size_type = size_t;
+	using difference_type = ptrdiff_t;
+
+	/// Constructor
+	inline					STLAllocator() = default;
+
+	/// Constructor from other allocator
+	template <typename T2>
+	inline					STLAllocator(const STLAllocator<T2> &) { }
+
+	/// Allocate memory
+	inline pointer			allocate(size_type inN)
+	{
+		if constexpr (alignof(T) > (JPH_CPU_ADDRESS_BITS == 32? 8 : 16))
+			return (pointer)AlignedAllocate(inN * sizeof(value_type), alignof(T));
+		else
+			return (pointer)Allocate(inN * sizeof(value_type));
+	}
+
+	/// Free memory
+	inline void				deallocate(pointer inPointer, size_type)
+	{
+		if constexpr (alignof(T) > (JPH_CPU_ADDRESS_BITS == 32? 8 : 16))
+			AlignedFree(inPointer);
+		else
+			Free(inPointer);
+	}
+
+	/// Allocators are stateless so assumed to be equal
+	inline bool				operator == (const STLAllocator<T> &) const
+	{
+		return true;
+	}
+
+	inline bool				operator != (const STLAllocator<T> &) const
+	{
+		return false;
+	}
+
+	/// Converting to allocator for other type
+	template <typename T2>
+	struct rebind
+	{
+		using other = STLAllocator<T2>;
+	};
+};
+
+#else
+
+template <typename T> using STLAllocator = allocator<T>;
+
+#endif // !JPH_DISABLE_CUSTOM_ALLOCATOR
+
+// Declare STL containers that use our allocator
+template <class T> using Array = vector<T, STLAllocator<T>>;
+using String = basic_string<char, char_traits<char>, STLAllocator<char>>;
+using IStringStream = basic_istringstream<char, char_traits<char>, STLAllocator<char>>;
+
+JPH_NAMESPACE_END
+
+#if !defined(JPH_PLATFORM_WINDOWS) && !defined(JPH_DISABLE_CUSTOM_ALLOCATOR)
+
+namespace std
+{
+	/// Declare std::hash for String, for some reason on Linux based platforms template deduction takes the wrong variant
+	template <> 
+	struct hash<JPH::String>
+	{
+		inline size_t operator () (const JPH::String &inRHS) const
+		{
+			return hash<string_view> { } (inRHS);
+		}
+	};
+}
+
+#endif // !JPH_PLATFORM_WINDOWS && !JPH_DISABLE_CUSTOM_ALLOCATOR

+ 7 - 7
Jolt/Core/StaticArray.h

@@ -22,7 +22,7 @@ public:
 	{
 		JPH_ASSERT(inList.size() <= N);
 		for (typename initializer_list<T>::iterator i = inList.begin(); i != inList.end(); ++i)
-			new (reinterpret_cast<T *>(&mElements[mSize++])) T(*i);
+			::new (reinterpret_cast<T *>(&mElements[mSize++])) T(*i);
 	}
 
 	/// Copy constructor
@@ -30,7 +30,7 @@ public:
 	{
 		while (mSize < inRHS.mSize)
 		{
-			new (&mElements[mSize]) T(inRHS[mSize]);
+			::new (&mElements[mSize]) T(inRHS[mSize]);
 			++mSize;
 		}
 	}
@@ -56,7 +56,7 @@ public:
 	void				push_back(const T &inElement)
 	{
 		JPH_ASSERT(mSize < N);
-		new (&mElements[mSize++]) T(inElement);
+		::new (&mElements[mSize++]) T(inElement);
 	}
 
 	/// Construct element at the back of the array
@@ -64,7 +64,7 @@ public:
 	void				emplace_back(A &&... inElement)
 	{	
 		JPH_ASSERT(mSize < N);
-		new (&mElements[mSize++]) T(forward<A>(inElement)...);
+		::new (&mElements[mSize++]) T(forward<A>(inElement)...);
 	}
 
 	/// Remove element from the back of the array
@@ -98,7 +98,7 @@ public:
 		JPH_ASSERT(inNewSize <= N);
 		if (!is_trivially_constructible<T>() && mSize < inNewSize)
 			for (T *element = reinterpret_cast<T *>(mElements) + mSize, *element_end = reinterpret_cast<T *>(mElements) + inNewSize; element < element_end; ++element)
-				new (element) T;
+				::new (element) T;
 		else if (!is_trivially_destructible<T>() && mSize > inNewSize)
 			for (T *element = reinterpret_cast<T *>(mElements) + inNewSize, *element_end = reinterpret_cast<T *>(mElements) + mSize; element < element_end; ++element)
 				element->~T();
@@ -214,7 +214,7 @@ public:
 
 			while (mSize < rhs_size)
 			{
-				new (&mElements[mSize]) T(inRHS[mSize]);
+				::new (&mElements[mSize]) T(inRHS[mSize]);
 				++mSize;
 			}
 		}
@@ -235,7 +235,7 @@ public:
 
 			while (mSize < rhs_size)
 			{
-				new (&mElements[mSize]) T(inRHS[mSize]);
+				::new (&mElements[mSize]) T(inRHS[mSize]);
 				++mSize;
 			}
 		}

+ 6 - 5
Jolt/Core/StreamIn.h

@@ -32,12 +32,12 @@ public:
 	template <class T, class A>
 	void				Read(vector<T, A> &outT)
 	{
-		typename vector<T>::size_type len = outT.size(); // Initialize to previous array size, this is used for validation in the StateRecorder class
+		typename Array<T>::size_type len = outT.size(); // Initialize to previous array size, this is used for validation in the StateRecorder class
 		Read(len);
 		if (!IsEOF() && !IsFailed())
 		{
 			outT.resize(len);
-			for (typename vector<T>::size_type i = 0; i < len; ++i)
+			for (typename Array<T>::size_type i = 0; i < len; ++i)
 				Read(outT[i]);
 		}
 		else
@@ -45,14 +45,15 @@ public:
 	}
 
 	/// Read a string from the binary stream (reads the number of characters and then the characters)
-	void				Read(string &outString)
+	template <class Type, class Traits, class Allocator>
+	void				Read(basic_string<Type, Traits, Allocator> &outString)
 	{
-		string::size_type len = 0;
+		typename basic_string<Type, Traits, Allocator>::size_type len = 0;
 		Read(len);
 		if (!IsEOF() && !IsFailed())
 		{
 			outString.resize(len);
-			ReadBytes(outString.data(), len);
+			ReadBytes(outString.data(), len * sizeof(Type));
 		}
 		else
 			outString.clear();

+ 6 - 5
Jolt/Core/StreamOut.h

@@ -29,20 +29,21 @@ public:
 	template <class T, class A>
 	void				Write(const vector<T, A> &inT)
 	{
-		typename vector<T>::size_type len = inT.size();
+		typename Array<T>::size_type len = inT.size();
 		Write(len);
 		if (!IsFailed())
-			for (typename vector<T>::size_type i = 0; i < len; ++i)
+			for (typename Array<T>::size_type i = 0; i < len; ++i)
 				Write(inT[i]);
 	}
 
 	/// Write a string to the binary stream (writes the number of characters and then the characters)
-	void				Write(const string &inString)
+	template <class Type, class Traits, class Allocator>
+	void				Write(const basic_string<Type, Traits, Allocator> &inString)
 	{
-		string::size_type len = inString.size();
+		typename basic_string<Type, Traits, Allocator>::size_type len = inString.size();
 		Write(len);
 		if (!IsFailed())
-			WriteBytes(inString.data(), len);
+			WriteBytes(inString.data(), len * sizeof(Type));
 	}
 
 	/// Write a Vec3 (don't write W)

+ 11 - 11
Jolt/Core/StringTools.cpp

@@ -11,7 +11,7 @@ JPH_SUPPRESS_WARNINGS_STD_END
 
 JPH_NAMESPACE_BEGIN
 
-string StringFormat(const char *inFMT, ...)
+String StringFormat(const char *inFMT, ...)
 {
 	char buffer[1024];
 
@@ -20,16 +20,16 @@ string StringFormat(const char *inFMT, ...)
 	va_start(list, inFMT);
 	vsnprintf(buffer, sizeof(buffer), inFMT, list);
 
-	return string(buffer);
+	return String(buffer);
 }
 
-void StringReplace(string &ioString, const string_view &inSearch, const string_view &inReplace)
+void StringReplace(String &ioString, const string_view &inSearch, const string_view &inReplace)
 {
 	size_t index = 0;
 	for (;;)
 	{
 		 index = ioString.find(inSearch, index);
-		 if (index == std::string::npos) 
+		 if (index == String::npos) 
 			 break;
 
 		 ioString.replace(index, inSearch.size(), inReplace);
@@ -38,7 +38,7 @@ void StringReplace(string &ioString, const string_view &inSearch, const string_v
 	}
 }
 
-void StringToVector(const string_view &inString, vector<string> &outVector, const string_view &inDelimiter, bool inClearVector)
+void StringToVector(const string_view &inString, Array<String> &outVector, const string_view &inDelimiter, bool inClearVector)
 {
 	JPH_ASSERT(inDelimiter.size() > 0);
 
@@ -51,11 +51,11 @@ void StringToVector(const string_view &inString, vector<string> &outVector, cons
 		return;
 
 	// Start with initial string
-	string s(inString);
+	String s(inString);
 
 	// Add to vector while we have a delimiter
 	size_t i;
-	while (!s.empty() && (i = s.find(inDelimiter)) != string::npos)
+	while (!s.empty() && (i = s.find(inDelimiter)) != String::npos)
 	{
 		outVector.push_back(s.substr(0, i));
 		s.erase(0, i + inDelimiter.length());
@@ -65,12 +65,12 @@ void StringToVector(const string_view &inString, vector<string> &outVector, cons
 	outVector.push_back(s);
 }
 
-void VectorToString(const vector<string> &inVector, string &outString, const string_view &inDelimiter)
+void VectorToString(const Array<String> &inVector, String &outString, const string_view &inDelimiter)
 {
 	// Ensure string empty
 	outString.clear();
 
-	for (const string &s : inVector)
+	for (const String &s : inVector)
 	{
 		// Add delimiter if not first element
 		if (!outString.empty())
@@ -81,9 +81,9 @@ void VectorToString(const vector<string> &inVector, string &outString, const str
 	}
 }
 
-string ToLower(const string_view &inString)
+String ToLower(const string_view &inString)
 {
-	string out;
+	String out;
 	out.reserve(inString.length());
 	for (char c : inString)
 		out.push_back((char)tolower(c));

+ 8 - 7
Jolt/Core/StringTools.h

@@ -7,13 +7,14 @@ JPH_NAMESPACE_BEGIN
 
 /// Create a formatted text string for debugging purposes.
 /// Note that this function has an internal buffer of 1024 characters, so long strings will be trimmed.
-string StringFormat(const char *inFMT, ...);
+String StringFormat(const char *inFMT, ...);
 
 /// Convert type to string
 template<typename T>
-string ConvertToString(const T &inValue)
+String ConvertToString(const T &inValue)
 {
-    ostringstream oss;
+	using OStringStream = basic_ostringstream<char, char_traits<char>, STLAllocator<char>>;
+    OStringStream oss;
     oss << inValue;
     return oss.str();
 }
@@ -32,16 +33,16 @@ constexpr uint64 HashString(const char *inString)
 }
 
 /// Replace substring with other string
-void StringReplace(string &ioString, const string_view &inSearch, const string_view &inReplace);
+void StringReplace(String &ioString, const string_view &inSearch, const string_view &inReplace);
 
 /// Convert a delimited string to an array of strings
-void StringToVector(const string_view &inString, vector<string> &outVector, const string_view &inDelimiter = ",", bool inClearVector = true);
+void StringToVector(const string_view &inString, Array<String> &outVector, const string_view &inDelimiter = ",", bool inClearVector = true);
 
 /// Convert an array strings to a delimited string
-void VectorToString(const vector<string> &inVector, string &outString, const string_view &inDelimiter = ",");
+void VectorToString(const Array<String> &inVector, String &outString, const string_view &inDelimiter = ",");
 
 /// Convert a string to lower case
-string ToLower(const string_view &inString);
+String ToLower(const string_view &inString);
 
 /// Converts the lower 4 bits of inNibble to a string that represents the number in binary format
 const char *NibbleToBinary(uint32 inNibble);

+ 9 - 4
Jolt/Core/TempAllocator.h

@@ -4,7 +4,6 @@
 #pragma once
 
 #include <Jolt/Core/NonCopyable.h>
-#include <Jolt/Core/Memory.h>
 
 JPH_NAMESPACE_BEGIN
 
@@ -15,6 +14,8 @@ JPH_NAMESPACE_BEGIN
 class TempAllocator : public NonCopyable
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Destructor
 	virtual							~TempAllocator() = default;
 
@@ -29,9 +30,11 @@ public:
 class TempAllocatorImpl final : public TempAllocator
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Constructs the allocator with a maximum allocatable size of inSize
 	explicit						TempAllocatorImpl(uint inSize) :
-		mBase(static_cast<uint8 *>(malloc(inSize))),
+		mBase(static_cast<uint8 *>(JPH::Allocate(inSize))),
 		mSize(inSize)
 	{
 	}
@@ -40,7 +43,7 @@ public:
 	virtual							~TempAllocatorImpl() override
 	{
 		JPH_ASSERT(mTop == 0);
-		free(mBase);
+		JPH::Free(mBase);
 	}
 
 	// See: TempAllocator
@@ -93,10 +96,12 @@ private:
 class TempAllocatorMalloc final : public TempAllocator
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	// See: TempAllocator
 	virtual void *					Allocate(uint inSize) override
 	{
-		return AlignedAlloc(inSize, 16);
+		return AlignedAllocate(inSize, 16);
 	}
 
 	// See: TempAllocator

+ 1 - 1
Jolt/Core/TickCounter.cpp

@@ -79,7 +79,7 @@ static const uint64 sProcessorTicksPerSecond = []() {
 			{
 				// Find ':'
 				string::size_type pos = line.find(':', num_chars);
-				if (pos != string::npos)
+				if (pos != String::npos)
 				{		
 					// Convert to number
 					string freq = line.substr(pos + 1);

+ 14 - 0
Jolt/Core/UnorderedMap.h

@@ -0,0 +1,14 @@
+// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
+// SPDX-License-Identifier: MIT
+
+#pragma once
+
+JPH_SUPPRESS_WARNINGS_STD_BEGIN
+#include <unordered_map>
+JPH_SUPPRESS_WARNINGS_STD_END
+
+JPH_NAMESPACE_BEGIN
+
+template <class Key, class T, class Hash = hash<Key>, class KeyEqual = equal_to<Key>> using UnorderedMap = unordered_map<Key, T, Hash, KeyEqual, STLAllocator<pair<const Key, T>>>;
+
+JPH_NAMESPACE_END

+ 14 - 0
Jolt/Core/UnorderedSet.h

@@ -0,0 +1,14 @@
+// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
+// SPDX-License-Identifier: MIT
+
+#pragma once
+
+JPH_SUPPRESS_WARNINGS_STD_BEGIN
+#include <unordered_set>
+JPH_SUPPRESS_WARNINGS_STD_END
+
+JPH_NAMESPACE_BEGIN
+
+template <class Key, class Hash = hash<Key>, class KeyEqual = equal_to<Key>> using UnorderedSet = unordered_set<Key, Hash, KeyEqual, STLAllocator<Key>>;
+
+JPH_NAMESPACE_END

+ 2 - 0
Jolt/Geometry/AABox.h

@@ -14,6 +14,8 @@ JPH_NAMESPACE_BEGIN
 class [[nodiscard]] AABox
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Constructor
 					AABox()												: mMin(Vec3::sReplicate(FLT_MAX)), mMax(Vec3::sReplicate(-FLT_MAX)) { }
 					AABox(Vec3Arg inMin, Vec3Arg inMax)					: mMin(inMin), mMax(inMax) { }

+ 8 - 8
Jolt/Geometry/ConvexHullBuilder.cpp

@@ -7,9 +7,9 @@
 #include <Jolt/Geometry/ConvexHullBuilder2D.h>
 #include <Jolt/Geometry/ClosestPoint.h>
 #include <Jolt/Core/StringTools.h>
+#include <Jolt/Core/UnorderedSet.h>
 
 JPH_SUPPRESS_WARNINGS_STD_BEGIN
-#include <unordered_set>
 #include <fstream>
 JPH_SUPPRESS_WARNINGS_STD_END
 
@@ -246,7 +246,7 @@ float ConvexHullBuilder::DetermineCoplanarDistance() const
 
 int ConvexHullBuilder::GetNumVerticesUsed() const
 {
-	unordered_set<int> used_verts;
+	UnorderedSet<int> used_verts;
 	for (Face *f : mFaces)
 	{
 		Edge *e = f->mFirstEdge;
@@ -259,12 +259,12 @@ int ConvexHullBuilder::GetNumVerticesUsed() const
 	return (int)used_verts.size();
 }
 
-bool ConvexHullBuilder::ContainsFace(const vector<int> &inIndices) const
+bool ConvexHullBuilder::ContainsFace(const Array<int> &inIndices) const
 {
 	for (Face *f : mFaces)
 	{
 		Edge *e = f->mFirstEdge;
-		vector<int>::const_iterator index = find(inIndices.begin(), inIndices.end(), e->mStartIdx);
+		Array<int>::const_iterator index = find(inIndices.begin(), inIndices.end(), e->mStartIdx);
 		if (index != inIndices.end())
 		{
 			size_t matches = 0;
@@ -404,13 +404,13 @@ ConvexHullBuilder::EResult ConvexHullBuilder::Initialize(int inMaxVertices, floa
 		// First project all points in 2D space
 		Vec3 base1 = initial_plane_normal.GetNormalizedPerpendicular();
 		Vec3 base2 = initial_plane_normal.Cross(base1);
-		vector<Vec3> positions_2d;
+		Array<Vec3> positions_2d;
 		positions_2d.reserve(mPositions.size());
 		for (Vec3 v : mPositions)
 			positions_2d.push_back(Vec3(base1.Dot(v), base2.Dot(v), 0));
 
 		// Build hull
-		vector<int> edges_2d;
+		Array<int> edges_2d;
 		ConvexHullBuilder2D builder_2d(positions_2d);
 		ConvexHullBuilder2D::EResult result = builder_2d.Initialize(idx1, idx2, idx3, inMaxVertices, inTolerance, edges_2d);
 
@@ -419,7 +419,7 @@ ConvexHullBuilder::EResult ConvexHullBuilder::Initialize(int inMaxVertices, floa
 		Face *f2 = CreateFace();
 
 		// Create edges for face 1
-		vector<Edge *> edges_f1;
+		Array<Edge *> edges_f1;
 		edges_f1.reserve(edges_2d.size());
 		for (int start_idx : edges_2d)
 		{
@@ -433,7 +433,7 @@ ConvexHullBuilder::EResult ConvexHullBuilder::Initialize(int inMaxVertices, floa
 		edges_f1.back()->mNextEdge = f1->mFirstEdge;
 
 		// Create edges for face 2
-		vector<Edge *> edges_f2;
+		Array<Edge *> edges_f2;
 		edges_f2.reserve(edges_2d.size());
 		for (int i = (int)edges_2d.size() - 1; i >= 0; --i)
 		{

+ 10 - 6
Jolt/Geometry/ConvexHullBuilder.h

@@ -26,6 +26,8 @@ public:
 	class Edge : public NonCopyable
 	{
 	public:
+		JPH_OVERRIDE_NEW_DELETE
+
 		/// Constructor
 						Edge(Face *inFace, int inStartIdx)	: mFace(inFace), mStartIdx(inStartIdx) { }
 
@@ -44,12 +46,14 @@ public:
 		int				mStartIdx;							///< Vertex index in mPositions that indicates the start vertex of this edge
 	};
 
-	using ConflictList = vector<int>;
+	using ConflictList = Array<int>;
 
 	/// Class that holds the information of one face
 	class Face : public NonCopyable
 	{
 	public:
+		JPH_OVERRIDE_NEW_DELETE
+
 		/// Destructor
 						~Face();
 
@@ -78,8 +82,8 @@ public:
 	};
 
 	// Typedefs
-	using Positions = vector<Vec3>;
-	using Faces = vector<Face *>;
+	using Positions = Array<Vec3>;
+	using Faces = Array<Face *>;
 
 	/// Constructor
 	explicit			ConvexHullBuilder(const Positions &inPositions);
@@ -108,7 +112,7 @@ public:
 	int					GetNumVerticesUsed() const;
 
 	/// Returns true if the hull contains a polygon with inIndices (counter clockwise indices in mPositions)
-	bool				ContainsFace(const vector<int> &inIndices) const;
+	bool				ContainsFace(const Array<int> &inIndices) const;
 
 	/// Calculate the center of mass and the volume of the current convex hull
 	void				GetCenterOfMassAndVolume(Vec3 &outCenterOfMass, float &outVolume) const;
@@ -142,7 +146,7 @@ private:
 	};
 
 	// Private typedefs
-	using FullEdges = vector<FullEdge>;
+	using FullEdges = Array<FullEdge>;
 
 	// Determine a suitable tolerance for detecting that points are coplanar
 	float				DetermineCoplanarDistance() const;
@@ -256,7 +260,7 @@ private:
 		int				mPositionIdx;						///< Index in mPositions
 		float			mDistanceSq;						///< Distance to the edge of closest face (should be > 0)
 	};
-	using CoplanarList = vector<Coplanar>;
+	using CoplanarList = Array<Coplanar>;
 
 	CoplanarList		mCoplanarList;						///< List of positions that are coplanar to a face but outside of the face, these are added to the hull at the end
 

+ 3 - 3
Jolt/Geometry/ConvexHullBuilder2D.cpp

@@ -106,7 +106,7 @@ void ConvexHullBuilder2D::ValidateEdges() const
 
 #endif // JPH_ENABLE_ASSERTS
 
-void ConvexHullBuilder2D::AssignPointToEdge(int inPositionIdx, const vector<Edge *> &inEdges) const
+void ConvexHullBuilder2D::AssignPointToEdge(int inPositionIdx, const Array<Edge *> &inEdges) const
 {
 	Vec3 point = mPositions[inPositionIdx];
 
@@ -185,7 +185,7 @@ ConvexHullBuilder2D::EResult ConvexHullBuilder2D::Initialize(int inIdx1, int inI
 	mNumEdges = 3;
 
 	// Build the initial conflict lists
-	vector<Edge *> edges { e1, e2, e3 };
+	Array<Edge *> edges { e1, e2, e3 };
 	for (Edge *edge : edges)
 		edge->CalculateNormalAndCenter(mPositions.data());
 	for (int idx = 0; idx < (int)mPositions.size(); ++idx)
@@ -262,7 +262,7 @@ ConvexHullBuilder2D::EResult ConvexHullBuilder2D::Initialize(int inIdx1, int inI
 		mNumEdges += 2;
 
 		// Calculate normals
-		vector<Edge *> new_edges { e1, e2 };
+		Array<Edge *> new_edges { e1, e2 };
 		for (Edge *new_edge : new_edges)
 			new_edge->CalculateNormalAndCenter(mPositions.data());
 

+ 6 - 4
Jolt/Geometry/ConvexHullBuilder2D.h

@@ -13,8 +13,8 @@ JPH_NAMESPACE_BEGIN
 class ConvexHullBuilder2D : public NonCopyable
 {
 public:
-	using Positions = vector<Vec3>; 
-	using Edges = vector<int>;
+	using Positions = Array<Vec3>; 
+	using Edges = Array<int>;
 
 	/// Constructor
 	/// @param inPositions Positions used to make the hull. Uses X and Y component of Vec3 only!
@@ -53,7 +53,7 @@ private:
 	/// Assigns a position to one of the supplied edges based on which edge is closest.
 	/// @param inPositionIdx Index of the position to add
 	/// @param inEdges List of edges to consider
-	void				AssignPointToEdge(int inPositionIdx, const vector<Edge *> &inEdges) const;
+	void				AssignPointToEdge(int inPositionIdx, const Array<Edge *> &inEdges) const;
 
 #ifdef JPH_CONVEX_BUILDER_2D_DEBUG
 	/// Draw state of algorithm
@@ -65,12 +65,14 @@ private:
 	void				ValidateEdges() const;
 #endif
 
-	using ConflictList = vector<int>;
+	using ConflictList = Array<int>;
 
 	/// Linked list of edges
 	class Edge
 	{
 	public:
+		JPH_OVERRIDE_NEW_DELETE
+
 		/// Constructor
 		explicit		Edge(int inStartIdx)						: mStartIdx(inStartIdx) { }
 

+ 2 - 0
Jolt/Geometry/Ellipse.h

@@ -12,6 +12,8 @@ JPH_NAMESPACE_BEGIN
 class Ellipse
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Construct ellipse with radius A along the X-axis and B along the Y-axis
 					Ellipse(float inA, float inB) : mA(inA), mB(inB) { JPH_ASSERT(inA > 0.0f); JPH_ASSERT(inB > 0.0f); }
 

+ 4 - 2
Jolt/Geometry/IndexedTriangle.h

@@ -11,6 +11,8 @@ JPH_NAMESPACE_BEGIN
 class IndexedTriangleNoMaterial
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Constructor
 					IndexedTriangleNoMaterial() = default;
 					IndexedTriangleNoMaterial(uint32 inI1, uint32 inI2, uint32 inI3)	{ mIdx[0] = inI1; mIdx[1] = inI2; mIdx[2] = inI3; }
@@ -98,8 +100,8 @@ public:
 	uint32			mMaterialIndex = 0;
 };
 
-using IndexedTriangleNoMaterialList = vector<IndexedTriangleNoMaterial>;
-using IndexedTriangleList = vector<IndexedTriangle>;
+using IndexedTriangleNoMaterialList = Array<IndexedTriangleNoMaterial>;
+using IndexedTriangleList = Array<IndexedTriangle>;
 
 JPH_NAMESPACE_END
 

+ 2 - 5
Jolt/Geometry/Indexify.cpp

@@ -3,12 +3,9 @@
 
 #include <Jolt/Jolt.h>
 
+#include <Jolt/Core/UnorderedMap.h>
 #include <Jolt/Geometry/Indexify.h>
 
-JPH_SUPPRESS_WARNINGS_STD_BEGIN
-#include <unordered_map>
-JPH_SUPPRESS_WARNINGS_STD_END
-
 JPH_NAMESPACE_BEGIN
 
 void Indexify(const TriangleList &inTriangles, VertexList &outVertices, IndexedTriangleList &outTriangles, float inVertexWeldDistance)
@@ -19,7 +16,7 @@ void Indexify(const TriangleList &inTriangles, VertexList &outVertices, IndexedT
 	outVertices.clear();
 
 	// Find unique vertices
-	unordered_map<Float3, uint32> vertex_map;
+	UnorderedMap<Float3, uint32> vertex_map;
 	for (const Triangle &t : inTriangles)
 		for (const Float3 &v : t.mV)
 		{

+ 2 - 0
Jolt/Geometry/OrientedBox.h

@@ -16,6 +16,8 @@ class AABox;
 class [[nodiscard]] OrientedBox
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Constructor
 					OrientedBox() = default;
 					OrientedBox(Mat44Arg inOrientation, Vec3Arg inHalfExtents)			: mOrientation(inOrientation), mHalfExtents(inHalfExtents) { }

+ 2 - 0
Jolt/Geometry/Plane.h

@@ -9,6 +9,8 @@ JPH_NAMESPACE_BEGIN
 class [[nodiscard]] Plane
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Constructor
 					Plane() = default;
 	explicit		Plane(Vec4Arg inNormalAndConstant)										: mNormalAndConstant(inNormalAndConstant) { }

+ 2 - 0
Jolt/Geometry/Sphere.h

@@ -10,6 +10,8 @@ JPH_NAMESPACE_BEGIN
 class [[nodiscard]] Sphere
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Constructor
 	inline				Sphere() = default;
 	inline				Sphere(const Float3 &inCenter, float inRadius)			: mCenter(inCenter), mRadius(inRadius) { }

+ 3 - 1
Jolt/Geometry/Triangle.h

@@ -9,6 +9,8 @@ JPH_NAMESPACE_BEGIN
 class Triangle
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Constructor
 					Triangle() = default;
 					Triangle(const Float3 &inV1, const Float3 &inV2, const Float3 &inV3) : mV { inV1, inV2, inV3 } { }
@@ -26,6 +28,6 @@ public:
 	uint32			mMaterialIndex = 0;			///< Follows mV[3] so that we can read mV as 4 vectors
 };
 
-using TriangleList = vector<Triangle>;
+using TriangleList = Array<Triangle>;
 
 JPH_NAMESPACE_END

+ 4 - 1
Jolt/Jolt.cmake

@@ -50,10 +50,13 @@ set(JOLT_PHYSICS_SRC_FILES
 	${JOLT_PHYSICS_ROOT}/Core/StringTools.cpp
 	${JOLT_PHYSICS_ROOT}/Core/StringTools.h
 	${JOLT_PHYSICS_ROOT}/Core/STLAlignedAllocator.h
+	${JOLT_PHYSICS_ROOT}/Core/STLAllocator.h
 	${JOLT_PHYSICS_ROOT}/Core/STLTempAllocator.h
 	${JOLT_PHYSICS_ROOT}/Core/TempAllocator.h
 	${JOLT_PHYSICS_ROOT}/Core/TickCounter.cpp
 	${JOLT_PHYSICS_ROOT}/Core/TickCounter.h
+	${JOLT_PHYSICS_ROOT}/Core/UnorderedMap.h
+	${JOLT_PHYSICS_ROOT}/Core/UnorderedSet.h
 	${JOLT_PHYSICS_ROOT}/Geometry/AABox.h
 	${JOLT_PHYSICS_ROOT}/Geometry/AABox4.h
 	${JOLT_PHYSICS_ROOT}/Geometry/ClipPoly.h
@@ -401,6 +404,6 @@ target_precompile_headers(Jolt PRIVATE ${JOLT_PHYSICS_ROOT}/Jolt.h)
 target_compile_definitions(Jolt PUBLIC "$<$<CONFIG:Debug>:_DEBUG;JPH_PROFILE_ENABLED;JPH_DEBUG_RENDERER>")
 target_compile_definitions(Jolt PUBLIC "$<$<CONFIG:Release>:NDEBUG;JPH_PROFILE_ENABLED;JPH_DEBUG_RENDERER>")
 target_compile_definitions(Jolt PUBLIC "$<$<CONFIG:Distribution>:NDEBUG>")
-target_compile_definitions(Jolt PUBLIC "$<$<CONFIG:ReleaseASAN>:NDEBUG;JPH_PROFILE_ENABLED;JPH_DISABLE_TEMP_ALLOCATOR;JPH_DEBUG_RENDERER>")
+target_compile_definitions(Jolt PUBLIC "$<$<CONFIG:ReleaseASAN>:NDEBUG;JPH_PROFILE_ENABLED;JPH_DISABLE_TEMP_ALLOCATOR;JPH_DISABLE_CUSTOM_ALLOCATOR;JPH_DEBUG_RENDERER>")
 target_compile_definitions(Jolt PUBLIC "$<$<CONFIG:ReleaseUBSAN>:NDEBUG;JPH_PROFILE_ENABLED;JPH_DEBUG_RENDERER>")
 target_compile_definitions(Jolt PUBLIC "$<$<CONFIG:ReleaseCoverage>:NDEBUG>")

+ 2 - 0
Jolt/Jolt.h

@@ -5,6 +5,8 @@
 
 // Project includes
 #include <Jolt/Core/Core.h>
+#include <Jolt/Core/Memory.h>
+#include <Jolt/Core/STLAllocator.h>
 #include <Jolt/Core/IssueReporting.h>
 #include <Jolt/Math/Math.h>
 #include <Jolt/Math/Vec4.h>

+ 2 - 0
Jolt/Math/DVec3.h

@@ -14,6 +14,8 @@ JPH_NAMESPACE_BEGIN
 class [[nodiscard]] DVec3
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 #ifdef JPH_FLOATING_POINT_EXCEPTIONS_ENABLED
 	/// Internal helper function that checks that W is equal to Z, so e.g. dividing by it should not generate div by 0
 	JPH_INLINE void				CheckW() const									{ JPH_ASSERT(reinterpret_cast<const uint64 *>(mD32)[2] == reinterpret_cast<const uint64 *>(mD32)[3]); } // Avoid asserts when both components are NaN

+ 2 - 0
Jolt/Math/Float2.h

@@ -9,6 +9,8 @@ JPH_NAMESPACE_BEGIN
 class [[nodiscard]] Float2
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 						Float2() = default; ///< Intentionally not initialized for performance reasons
 						Float2(const Float2 &inRHS) = default;
 						Float2(float inX, float inY)					: x(inX), y(inY) { }

+ 3 - 1
Jolt/Math/Float3.h

@@ -11,6 +11,8 @@ JPH_NAMESPACE_BEGIN
 class [[nodiscard]] Float3
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 				Float3() = default; ///< Intentionally not initialized for performance reasons
 				Float3(const Float3 &inRHS) = default;
 				Float3(float inX, float inY, float inZ) : x(inX), y(inY), z(inZ) { }
@@ -36,7 +38,7 @@ public:
 	float		z;
 };
 
-using VertexList = vector<Float3>;
+using VertexList = Array<Float3>;
 
 static_assert(is_trivial<Float3>(), "Is supposed to be a trivial type!");
 

+ 2 - 0
Jolt/Math/Float4.h

@@ -9,6 +9,8 @@ JPH_NAMESPACE_BEGIN
 class [[nodiscard]] Float4
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 				Float4() = default; ///< Intentionally not initialized for performance reasons
 				Float4(const Float4 &inRHS) = default;
 				Float4(float inX, float inY, float inZ, float inW) : x(inX), y(inY), z(inZ), w(inW) { }

+ 2 - 0
Jolt/Math/Mat44.h

@@ -11,6 +11,8 @@ JPH_NAMESPACE_BEGIN
 class [[nodiscard]] alignas(16) Mat44
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	// Underlying column type
 	using Type = Vec4::Type;
 

+ 2 - 0
Jolt/Math/Quat.h

@@ -31,6 +31,8 @@ JPH_NAMESPACE_BEGIN
 class [[nodiscard]] alignas(16) Quat
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	///@name Constructors
 	///@{
 	inline						Quat() = default; ///< Intentionally not initialized for performance reasons

+ 2 - 0
Jolt/Math/UVec4.h

@@ -10,6 +10,8 @@ JPH_NAMESPACE_BEGIN
 class [[nodiscard]] alignas(16) UVec4
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	// Underlying vector type
 #if defined(JPH_USE_SSE)
 	using Type = __m128i;

+ 2 - 0
Jolt/Math/UVec8.h

@@ -10,6 +10,8 @@ JPH_NAMESPACE_BEGIN
 class [[nodiscard]] UVec8
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 								UVec8() = default; ///< Intentionally not initialized for performance reasons
 								UVec8(const UVec8 &inRHS) = default;
 	JPH_INLINE					UVec8(__m256i inRHS) : mValue(inRHS)				{ }

+ 1 - 5
Jolt/Math/Vec3.cpp

@@ -3,13 +3,9 @@
 
 #include <Jolt/Jolt.h>
 
+#include <Jolt/Core/UnorderedSet.h>
 #include <Jolt/Math/Vec3.h>
 
-JPH_SUPPRESS_WARNINGS_STD_BEGIN
-#include <unordered_set>
-JPH_SUPPRESS_WARNINGS_STD_END
-
-
 JPH_NAMESPACE_BEGIN
 
 static void sCreateVertices(unordered_set<Vec3> &ioVertices, Vec3Arg inDir1, Vec3Arg inDir2, Vec3Arg inDir3, int inLevel)

+ 2 - 0
Jolt/Math/Vec3.h

@@ -14,6 +14,8 @@ JPH_NAMESPACE_BEGIN
 class [[nodiscard]] alignas(16) Vec3
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	// Underlying vector type
 #if defined(JPH_USE_SSE)
 	using Type = __m128;

+ 2 - 0
Jolt/Math/Vec4.h

@@ -12,6 +12,8 @@ JPH_NAMESPACE_BEGIN
 class [[nodiscard]] alignas(16) Vec4
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	// Underlying vector type
 #if defined(JPH_USE_SSE)
 	using Type = __m128;

+ 2 - 0
Jolt/Math/Vec8.h

@@ -10,6 +10,8 @@ JPH_NAMESPACE_BEGIN
 class [[nodiscard]] Vec8
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Constructor
 								Vec8() = default; ///< Intentionally not initialized for performance reasons
 								Vec8(const Vec8 &inRHS) = default;

+ 2 - 2
Jolt/ObjectStream/GetPrimitiveTypeOfType.h

@@ -7,7 +7,7 @@
 
 JPH_NAMESPACE_BEGIN
 
-/// Helper functions to get the underlying RTTI type of a type (so e.g. vector<sometype> will return sometype)
+/// Helper functions to get the underlying RTTI type of a type (so e.g. Array<sometype> will return sometype)
 template <class T>				
 const RTTI *GetPrimitiveTypeOfType(T *)
 { 
@@ -33,7 +33,7 @@ const RTTI *GetPrimitiveTypeOfType(RefConst<T> *)
 }
 
 template <class T>				
-const RTTI *GetPrimitiveTypeOfType(vector<T> *)
+const RTTI *GetPrimitiveTypeOfType(Array<T> *)
 { 
 	return GetPrimitiveTypeOfType((T *)nullptr);
 }

+ 7 - 7
Jolt/ObjectStream/ObjectStream.h

@@ -39,7 +39,7 @@ class IObjectStreamIn : public ObjectStream
 public:
 	///@name Input type specific operations
 	virtual bool				ReadDataType(EOSDataType &outType) = 0;
-	virtual bool				ReadName(string &outName) = 0;
+	virtual bool				ReadName(String &outName) = 0;
 	virtual bool				ReadIdentifier(Identifier &outIdentifier) = 0;
 	virtual bool				ReadCount(uint32 &outCount) = 0;
 
@@ -51,7 +51,7 @@ public:
 	virtual bool				ReadPrimitiveData(uint64 &outPrimitive) = 0;
 	virtual bool				ReadPrimitiveData(float &outPrimitive) = 0;
 	virtual bool				ReadPrimitiveData(bool &outPrimitive) = 0;
-	virtual bool				ReadPrimitiveData(string &outPrimitive) = 0;
+	virtual bool				ReadPrimitiveData(String &outPrimitive) = 0;
 	virtual bool				ReadPrimitiveData(Float3 &outPrimitive) = 0;
 	virtual bool				ReadPrimitiveData(Vec3 &outPrimitive) = 0;
 	virtual bool				ReadPrimitiveData(Vec4 &outPrimitive) = 0;
@@ -81,7 +81,7 @@ public:
 	virtual void				WritePrimitiveData(const uint64 &inPrimitive) = 0;
 	virtual void				WritePrimitiveData(const float &inPrimitive) = 0;
 	virtual void				WritePrimitiveData(const bool &inPrimitive) = 0;
-	virtual void				WritePrimitiveData(const string &inPrimitive) = 0;
+	virtual void				WritePrimitiveData(const String &inPrimitive) = 0;
 	virtual void				WritePrimitiveData(const Float3 &inPrimitive) = 0;
 	virtual void				WritePrimitiveData(const Vec3 &inPrimitive) = 0;
 	virtual void				WritePrimitiveData(const Vec4 &inPrimitive) = 0;
@@ -110,7 +110,7 @@ public:
 
 // Define serialization templates
 template <class T>
-bool OSIsType(vector<T> *, int inArrayDepth, EOSDataType inDataType, const char *inClassName)	
+bool OSIsType(Array<T> *, int inArrayDepth, EOSDataType inDataType, const char *inClassName)	
 { 
 	return (inArrayDepth > 0 && OSIsType((T *)nullptr, inArrayDepth - 1, inDataType, inClassName)); 
 }
@@ -141,7 +141,7 @@ bool OSIsType(RefConst<T> *, int inArrayDepth, EOSDataType inDataType, const cha
 
 /// Define serialization templates for dynamic arrays
 template <class T>
-bool OSReadData(IObjectStreamIn &ioStream, vector<T> &inArray)
+bool OSReadData(IObjectStreamIn &ioStream, Array<T> &inArray)
 {
 	bool continue_reading = true;
 
@@ -219,14 +219,14 @@ bool OSReadData(IObjectStreamIn &ioStream, RefConst<T> &inRef)
 
 // Define serialization templates for dynamic arrays
 template <class T>
-void OSWriteDataType(IObjectStreamOut &ioStream, vector<T> *)		
+void OSWriteDataType(IObjectStreamOut &ioStream, Array<T> *)		
 { 
 	ioStream.WriteDataType(EOSDataType::Array); 
 	OSWriteDataType(ioStream, (T *)nullptr); 
 }
 
 template <class T>
-void OSWriteData(IObjectStreamOut &ioStream, const vector<T> &inArray)
+void OSWriteData(IObjectStreamOut &ioStream, const Array<T> &inArray)
 {
 	// Write size of array
 	ioStream.HintNextItem();

+ 2 - 2
Jolt/ObjectStream/ObjectStreamBinaryIn.cpp

@@ -21,7 +21,7 @@ bool ObjectStreamBinaryIn::ReadDataType(EOSDataType &outType)
 	return true;
 }
 
-bool ObjectStreamBinaryIn::ReadName(string &outName)
+bool ObjectStreamBinaryIn::ReadName(String &outName)
 {
 	return ReadPrimitiveData(outName);
 }
@@ -107,7 +107,7 @@ bool ObjectStreamBinaryIn::ReadPrimitiveData(bool &outPrimitive)
 	return true;
 }
 
-bool ObjectStreamBinaryIn::ReadPrimitiveData(string &outPrimitive)
+bool ObjectStreamBinaryIn::ReadPrimitiveData(String &outPrimitive)
 {
 	// Read length or ID of string
 	uint32 len;

+ 5 - 3
Jolt/ObjectStream/ObjectStreamBinaryIn.h

@@ -11,12 +11,14 @@ JPH_NAMESPACE_BEGIN
 class ObjectStreamBinaryIn : public ObjectStreamIn
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Constructor
 	explicit 					ObjectStreamBinaryIn(istream &inStream);
 
 	///@name Input type specific operations
 	virtual bool				ReadDataType(EOSDataType &outType) override;
-	virtual bool				ReadName(string &outName) override;
+	virtual bool				ReadName(String &outName) override;
 	virtual bool				ReadIdentifier(Identifier &outIdentifier) override;
 	virtual bool				ReadCount(uint32 &outCount) override;
 
@@ -27,7 +29,7 @@ public:
 	virtual bool				ReadPrimitiveData(uint64 &outPrimitive) override;
 	virtual bool				ReadPrimitiveData(float &outPrimitive) override;
 	virtual bool				ReadPrimitiveData(bool &outPrimitive) override;
-	virtual bool				ReadPrimitiveData(string &outPrimitive) override;
+	virtual bool				ReadPrimitiveData(String &outPrimitive) override;
 	virtual bool				ReadPrimitiveData(Float3 &outPrimitive) override;
 	virtual bool				ReadPrimitiveData(Vec3 &outPrimitive) override;
 	virtual bool				ReadPrimitiveData(Vec4 &outPrimitive) override;
@@ -35,7 +37,7 @@ public:
 	virtual bool				ReadPrimitiveData(Mat44 &outPrimitive) override;
 
 private:
-	using StringTable = unordered_map<uint32, string>;
+	using StringTable = UnorderedMap<uint32, String>;
 
 	StringTable					mStringTable;
 	uint32						mNextStringID = 0x80000000;

+ 3 - 3
Jolt/ObjectStream/ObjectStreamBinaryOut.cpp

@@ -11,7 +11,7 @@ JPH_NAMESPACE_BEGIN
 ObjectStreamBinaryOut::ObjectStreamBinaryOut(ostream &inStream) :
 	ObjectStreamOut(inStream)
 {
-	string header;
+	String header;
 	header = StringFormat("BOS%2d.%02d", ObjectStream::sVersion, ObjectStream::sRevision);
 	mStream.write(header.c_str(), header.size());
 }
@@ -23,7 +23,7 @@ void ObjectStreamBinaryOut::WriteDataType(EOSDataType inType)
 
 void ObjectStreamBinaryOut::WriteName(const char *inName)
 {
-	WritePrimitiveData(string(inName));
+	WritePrimitiveData(String(inName));
 }
 
 void ObjectStreamBinaryOut::WriteIdentifier(Identifier inIdentifier)
@@ -71,7 +71,7 @@ void ObjectStreamBinaryOut::WritePrimitiveData(const bool &inPrimitive)
 	mStream.write((const char *)&inPrimitive, sizeof(inPrimitive));
 }
 
-void ObjectStreamBinaryOut::WritePrimitiveData(const string &inPrimitive)
+void ObjectStreamBinaryOut::WritePrimitiveData(const String &inPrimitive)
 {
 	// Empty strings are trivial
 	if (inPrimitive.empty())

+ 4 - 2
Jolt/ObjectStream/ObjectStreamBinaryOut.h

@@ -11,6 +11,8 @@ JPH_NAMESPACE_BEGIN
 class ObjectStreamBinaryOut : public ObjectStreamOut
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Constructor and destructor
 	explicit 					ObjectStreamBinaryOut(ostream &inStream);
 
@@ -27,7 +29,7 @@ public:
 	virtual void				WritePrimitiveData(const uint64 &inPrimitive) override;
 	virtual void				WritePrimitiveData(const float &inPrimitive) override;
 	virtual void				WritePrimitiveData(const bool &inPrimitive) override;
-	virtual void				WritePrimitiveData(const string &inPrimitive) override;
+	virtual void				WritePrimitiveData(const String &inPrimitive) override;
 	virtual void				WritePrimitiveData(const Float3 &inPrimitive) override;
 	virtual void				WritePrimitiveData(const Vec3 &inPrimitive) override;
 	virtual void				WritePrimitiveData(const Vec4 &inPrimitive) override;
@@ -35,7 +37,7 @@ public:
 	virtual void				WritePrimitiveData(const Mat44 &inPrimitive) override;
 
 private:
-	using StringTable = unordered_map<string, uint32>;
+	using StringTable = UnorderedMap<String, uint32>;
 
 	StringTable					mStringTable;
 	uint32						mNextStringID = 0x80000000;

+ 7 - 10
Jolt/ObjectStream/ObjectStreamIn.cpp

@@ -4,15 +4,12 @@
 #include <Jolt/Jolt.h>
 
 #include <Jolt/Core/Factory.h>
+#include <Jolt/Core/UnorderedSet.h>
 #include <Jolt/ObjectStream/ObjectStreamIn.h>
 #include <Jolt/ObjectStream/ObjectStreamTextIn.h>
 #include <Jolt/ObjectStream/ObjectStreamBinaryIn.h>
 #include <Jolt/ObjectStream/SerializableObject.h>
 
-JPH_SUPPRESS_WARNINGS_STD_BEGIN
-#include <unordered_set>
-JPH_SUPPRESS_WARNINGS_STD_END
-
 JPH_NAMESPACE_BEGIN
 
 ObjectStreamIn::ObjectStreamIn(istream &inStream) :
@@ -79,7 +76,7 @@ ObjectStreamIn *ObjectStreamIn::Open(istream &inStream)
 
 void *ObjectStreamIn::Read(const RTTI *inRTTI)
 {
-	using ObjectSet = unordered_set<void *>;
+	using ObjectSet = UnorderedSet<void *>;
 
 	// Read all information on the stream
 	void *main_object = nullptr;
@@ -196,7 +193,7 @@ void *ObjectStreamIn::ReadObject(const RTTI *& outRTTI)
 {
 	// Read the object class
 	void *object = nullptr;
-	string class_name;
+	String class_name;
 	if (ReadName(class_name)) 
 	{
 		// Get class description
@@ -253,7 +250,7 @@ void *ObjectStreamIn::ReadObject(const RTTI *& outRTTI)
 bool ObjectStreamIn::ReadRTTI()
 {
 	// Read class name and find it's attribute info
-	string class_name;
+	String class_name;
 	if (!ReadName(class_name)) 
 		return false;
 
@@ -276,7 +273,7 @@ bool ObjectStreamIn::ReadRTTI()
 		AttributeDescription attribute;
 		
 		// Read name
-		string attribute_name;
+		String attribute_name;
 		if (!ReadName(attribute_name)) 
 			return false;
 		
@@ -488,9 +485,9 @@ bool ObjectStreamIn::SkipAttributeData(int inArrayDepth, EOSDataType inDataType,
 						break;
 					}
 				
-				case EOSDataType::T_string:
+				case EOSDataType::T_String:
 					{	
-						string temporary;
+						String temporary;
 						continue_reading = ReadPrimitiveData(temporary);
 						break;
 					}

+ 6 - 6
Jolt/ObjectStream/ObjectStreamIn.h

@@ -6,10 +6,10 @@
 #include <Jolt/ObjectStream/ObjectStream.h>
 #include <Jolt/Core/Reference.h>
 #include <Jolt/Core/RTTI.h>
+#include <Jolt/Core/UnorderedMap.h>
 
 JPH_SUPPRESS_WARNINGS_STD_BEGIN
 #include <fstream>
-#include <unordered_map>
 JPH_SUPPRESS_WARNINGS_STD_END
 
 JPH_NAMESPACE_BEGIN
@@ -101,7 +101,7 @@ private:
 	{
 		int						mArrayDepth = 0;
 		EOSDataType				mDataType = EOSDataType::Invalid;
-		string					mClassName;
+		String					mClassName;
 		int						mIndex = -1;
 	};
 
@@ -111,7 +111,7 @@ private:
 		explicit 				ClassDescription(const RTTI *inRTTI)					: mRTTI(inRTTI) { }
 
 		const RTTI *			mRTTI = nullptr;
-		vector<AttributeDescription>	mAttributes;
+		Array<AttributeDescription>	mAttributes;
 	};
 	
 	struct ObjectInfo
@@ -131,12 +131,12 @@ private:
 		const RTTI *			mRTTI;
 	};
 	
-	using IdentifierMap = unordered_map<Identifier, ObjectInfo>;
-	using ClassDescriptionMap = unordered_map<string, ClassDescription>;
+	using IdentifierMap = UnorderedMap<Identifier, ObjectInfo>;
+	using ClassDescriptionMap = UnorderedMap<String, ClassDescription>;
 
 	ClassDescriptionMap			mClassDescriptionMap;
 	IdentifierMap				mIdentifierMap;											///< Links identifier to an object pointer
-	vector<Link>				mUnresolvedLinks;										///< All pointers (links) are resolved after reading the entire file, e.g. when all object exist
+	Array<Link>					mUnresolvedLinks;										///< All pointers (links) are resolved after reading the entire file, e.g. when all object exist
 };
 
 JPH_NAMESPACE_END

+ 8 - 6
Jolt/ObjectStream/ObjectStreamOut.h

@@ -5,16 +5,18 @@
 
 #include <Jolt/ObjectStream/ObjectStream.h>
 #include <Jolt/Core/RTTI.h>
+#include <Jolt/Core/UnorderedMap.h>
+#include <Jolt/Core/UnorderedSet.h>
 
 JPH_SUPPRESS_WARNINGS_STD_BEGIN
 #include <queue>
 #include <fstream>
-#include <unordered_set>
-#include <unordered_map>
 JPH_SUPPRESS_WARNINGS_STD_END
 
 JPH_NAMESPACE_BEGIN
 
+template <class T> using Queue = queue<T, deque<T, STLAllocator<T>>>;
+
 /// ObjectStreamOut contains all logic for writing an object to disk. It is the base 
 /// class for the text and binary output streams (ObjectStreamTextOut and ObjectStreamBinaryOut).
 class ObjectStreamOut : public IObjectStreamOut
@@ -82,10 +84,10 @@ private:
 		const RTTI *			mRTTI;
 	};
 
-	using IdentifierMap = unordered_map<const void *, ObjectInfo>;
-	using ClassSet = unordered_set<const RTTI *>;
-	using ObjectQueue = queue<const void *>;
-	using ClassQueue = queue<const RTTI *>;
+	using IdentifierMap = UnorderedMap<const void *, ObjectInfo>;
+	using ClassSet = UnorderedSet<const RTTI *>;
+	using ObjectQueue = Queue<const void *>;
+	using ClassQueue = Queue<const RTTI *>;
 
 	Identifier					mNextIdentifier = sNullIdentifier + 1;						///< Next free identifier for this stream
 	IdentifierMap				mIdentifierMap;												///< Links object pointer to an identifier

+ 20 - 20
Jolt/ObjectStream/ObjectStreamTextIn.cpp

@@ -14,7 +14,7 @@ ObjectStreamTextIn::ObjectStreamTextIn(istream &inStream) :
 
 bool ObjectStreamTextIn::ReadDataType(EOSDataType &outType)
 {
-	string token;
+	String token;
 	if (ReadWord(token)) 
 	{
 		transform(token.begin(), token.end(), token.begin(), [](char inValue) { return (char)tolower(inValue); });
@@ -43,7 +43,7 @@ bool ObjectStreamTextIn::ReadDataType(EOSDataType &outType)
 		else if (token == "bool")
 			outType  = EOSDataType::T_bool;
 		else if (token == "string")
-			outType  = EOSDataType::T_string;
+			outType  = EOSDataType::T_String;
 		else if (token == "float3")
 			outType  = EOSDataType::T_Float3;
 		else if (token == "vec3")
@@ -64,14 +64,14 @@ bool ObjectStreamTextIn::ReadDataType(EOSDataType &outType)
 	return false;
 }
 
-bool ObjectStreamTextIn::ReadName(string &outName)
+bool ObjectStreamTextIn::ReadName(String &outName)
 {
 	return ReadWord(outName);
 }
 
 bool ObjectStreamTextIn::ReadIdentifier(Identifier &outIdentifier)
 {
-	string token;
+	String token;
 	if (!ReadWord(token))
 		return false;
 	outIdentifier = (uint32)std::strtoul(token.c_str(), nullptr, 16);
@@ -90,11 +90,11 @@ bool ObjectStreamTextIn::ReadCount(uint32 &outCount)
 
 bool ObjectStreamTextIn::ReadPrimitiveData(uint8 &outPrimitive)
 {
-	string token;
+	String token;
 	if (!ReadWord(token))
 		return false;
 	uint32 temporary;
-	istringstream stream(token);
+	IStringStream stream(token);
 	stream >> temporary;
 	if (!stream.fail())
 	{
@@ -106,11 +106,11 @@ bool ObjectStreamTextIn::ReadPrimitiveData(uint8 &outPrimitive)
 
 bool ObjectStreamTextIn::ReadPrimitiveData(uint16 &outPrimitive)
 {
-	string token;
+	String token;
 	if (!ReadWord(token))
 		return false;
 	uint32 temporary;
-	istringstream stream(token);
+	IStringStream stream(token);
 	stream >> temporary;
 	if (!stream.fail())
 	{
@@ -122,47 +122,47 @@ bool ObjectStreamTextIn::ReadPrimitiveData(uint16 &outPrimitive)
 
 bool ObjectStreamTextIn::ReadPrimitiveData(int &outPrimitive)
 {
-	string token;
+	String token;
 	if (!ReadWord(token))
 		return false;
-	istringstream stream(token);
+	IStringStream stream(token);
 	stream >> outPrimitive;
 	return !stream.fail();
 }
 
 bool ObjectStreamTextIn::ReadPrimitiveData(uint32 &outPrimitive)
 {
-	string token;
+	String token;
 	if (!ReadWord(token))
 		return false;
-	istringstream stream(token);
+	IStringStream stream(token);
 	stream >> outPrimitive;
 	return !stream.fail();
 }
 
 bool ObjectStreamTextIn::ReadPrimitiveData(uint64 &outPrimitive)
 {
-	string token;
+	String token;
 	if (!ReadWord(token))
 		return false;
-	istringstream stream(token);
+	IStringStream stream(token);
 	stream >> outPrimitive;
 	return !stream.fail();
 }
 
 bool ObjectStreamTextIn::ReadPrimitiveData(float &outPrimitive)
 {
-	string token;
+	String token;
 	if (!ReadWord(token))
 		return false;
-	istringstream stream(token);
+	IStringStream stream(token);
 	stream >> outPrimitive;
 	return !stream.fail();
 }
 
 bool ObjectStreamTextIn::ReadPrimitiveData(bool &outPrimitive)
 {
-	string token;
+	String token;
 	if (!ReadWord(token))
 		return false;
 	transform(token.begin(), token.end(), token.begin(), [](char inValue) { return (char)tolower(inValue); });
@@ -170,7 +170,7 @@ bool ObjectStreamTextIn::ReadPrimitiveData(bool &outPrimitive)
 	return outPrimitive || token == "false";
 }
 
-bool ObjectStreamTextIn::ReadPrimitiveData(string &outPrimitive)
+bool ObjectStreamTextIn::ReadPrimitiveData(String &outPrimitive)
 {
 	outPrimitive.clear();
 
@@ -191,7 +191,7 @@ bool ObjectStreamTextIn::ReadPrimitiveData(string &outPrimitive)
 		return false;
 
 	// Read string and interpret special characters
-	string	result;
+	String result;
 	bool escaped = false;
 	for (;;) 
 	{
@@ -311,7 +311,7 @@ bool ObjectStreamTextIn::ReadChar(char &outChar)
 	return !mStream.eof();
 }
 
-bool ObjectStreamTextIn::ReadWord(string &outWord)
+bool ObjectStreamTextIn::ReadWord(String &outWord)
 {
 	outWord.clear();
 

+ 5 - 3
Jolt/ObjectStream/ObjectStreamTextIn.h

@@ -11,12 +11,14 @@ JPH_NAMESPACE_BEGIN
 class ObjectStreamTextIn : public ObjectStreamIn
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Constructor
 	explicit					ObjectStreamTextIn(istream &inStream);
 
 	///@name Input type specific operations
 	virtual bool				ReadDataType(EOSDataType &outType) override;
-	virtual bool				ReadName(string &outName) override;
+	virtual bool				ReadName(String &outName) override;
 	virtual bool				ReadIdentifier(Identifier &outIdentifier) override;
 	virtual bool				ReadCount(uint32 &outCount) override;
 
@@ -27,7 +29,7 @@ public:
 	virtual bool				ReadPrimitiveData(uint64 &outPrimitive) override;
 	virtual bool				ReadPrimitiveData(float &outPrimitive) override;
 	virtual bool				ReadPrimitiveData(bool &outPrimitive) override;
-	virtual bool				ReadPrimitiveData(string &outPrimitive) override;
+	virtual bool				ReadPrimitiveData(String &outPrimitive) override;
 	virtual bool				ReadPrimitiveData(Float3 &outPrimitive) override;
 	virtual bool				ReadPrimitiveData(Vec3 &outPrimitive) override;
 	virtual bool				ReadPrimitiveData(Vec4 &outPrimitive) override;
@@ -36,7 +38,7 @@ public:
 
 private:
 	bool						ReadChar(char &outChar);
-	bool						ReadWord(string &outWord);
+	bool						ReadWord(String &outWord);
 };
 
 JPH_NAMESPACE_END

+ 5 - 5
Jolt/ObjectStream/ObjectStreamTextOut.cpp

@@ -30,7 +30,7 @@ void ObjectStreamTextOut::WriteDataType(EOSDataType inType)
 	case EOSDataType::T_uint64:		WriteWord("uint64");		break;
 	case EOSDataType::T_float:		WriteWord("float");			break;
 	case EOSDataType::T_bool:		WriteWord("bool");			break;
-	case EOSDataType::T_string:		WriteWord("string");		break;
+	case EOSDataType::T_String:		WriteWord("string");		break;
 	case EOSDataType::T_Float3:		WriteWord("float3");		break;
 	case EOSDataType::T_Vec3:		WriteWord("vec3");			break;
 	case EOSDataType::T_Vec4:		WriteWord("vec4");			break;
@@ -43,7 +43,7 @@ void ObjectStreamTextOut::WriteDataType(EOSDataType inType)
 
 void ObjectStreamTextOut::WriteName(const char *inName)
 {
-	WriteWord(string(inName) + " ");
+	WriteWord(String(inName) + " ");
 }
 
 void ObjectStreamTextOut::WriteIdentifier(Identifier inIdentifier)
@@ -145,14 +145,14 @@ void ObjectStreamTextOut::WritePrimitiveData(const Mat44 &inPrimitive)
 	WritePrimitiveData(inPrimitive.GetColumn4(3));
 }
 
-void ObjectStreamTextOut::WritePrimitiveData(const string &inPrimitive)
+void ObjectStreamTextOut::WritePrimitiveData(const String &inPrimitive)
 {
-	string temporary(inPrimitive);
+	String temporary(inPrimitive);
 	StringReplace(temporary, "\\", "\\\\");
 	StringReplace(temporary, "\n", "\\n");
 	StringReplace(temporary, "\t", "\\t");
 	StringReplace(temporary, "\"", "\\\"");
-	WriteWord(string("\"") + temporary + string("\""));
+	WriteWord(String("\"") + temporary + String("\""));
 }
 
 void ObjectStreamTextOut::HintNextItem()

+ 3 - 1
Jolt/ObjectStream/ObjectStreamTextOut.h

@@ -11,6 +11,8 @@ JPH_NAMESPACE_BEGIN
 class ObjectStreamTextOut : public ObjectStreamOut
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Constructor and destructor
 	explicit					ObjectStreamTextOut(ostream &inStream);
 
@@ -27,7 +29,7 @@ public:
 	virtual void				WritePrimitiveData(const uint64 &inPrimitive) override;
 	virtual void				WritePrimitiveData(const float &inPrimitive) override;
 	virtual void				WritePrimitiveData(const bool &inPrimitive) override;
-	virtual void				WritePrimitiveData(const string &inPrimitive) override;
+	virtual void				WritePrimitiveData(const String &inPrimitive) override;
 	virtual void				WritePrimitiveData(const Float3 &inPrimitive) override;
 	virtual void				WritePrimitiveData(const Vec3 &inPrimitive) override;
 	virtual void				WritePrimitiveData(const Vec4 &inPrimitive) override;

+ 1 - 1
Jolt/ObjectStream/ObjectStreamTypes.h

@@ -8,7 +8,7 @@ JPH_DECLARE_PRIMITIVE(uint32)
 JPH_DECLARE_PRIMITIVE(uint64)
 JPH_DECLARE_PRIMITIVE(float)
 JPH_DECLARE_PRIMITIVE(bool)
-JPH_DECLARE_PRIMITIVE(string)
+JPH_DECLARE_PRIMITIVE(String)
 JPH_DECLARE_PRIMITIVE(Float3)
 JPH_DECLARE_PRIMITIVE(Vec3)
 JPH_DECLARE_PRIMITIVE(Vec4)

+ 2 - 2
Jolt/ObjectStream/SerializableAttribute.h

@@ -50,7 +50,7 @@ public:
 	void						SetName(const char *inName)							{ mName = inName; }
 	const char *				GetName() const										{ return mName; }
 
-	/// In case this attribute contains an RTTI type, return it (note that a vector<sometype> will return the rtti of sometype)
+	/// In case this attribute contains an RTTI type, return it (note that a Array<sometype> will return the rtti of sometype)
 	const RTTI *				GetMemberPrimitiveType() const
 	{
 		return mGetMemberPrimitiveType();
@@ -87,7 +87,7 @@ private:
 	// Offset of the member relative to the class
 	uint						mMemberOffset;
 
-	// In case this attribute contains an RTTI type, return it (note that a vector<sometype> will return the rtti of sometype)
+	// In case this attribute contains an RTTI type, return it (note that a Array<sometype> will return the rtti of sometype)
 	pGetMemberPrimitiveType		mGetMemberPrimitiveType;
 
 	// Serialization operations

+ 1 - 1
Jolt/ObjectStream/TypeDeclarations.cpp

@@ -14,7 +14,7 @@ JPH_IMPLEMENT_RTTI_OUTSIDE_CLASS(uint32)		{ }
 JPH_IMPLEMENT_RTTI_OUTSIDE_CLASS(uint64)		{ }
 JPH_IMPLEMENT_RTTI_OUTSIDE_CLASS(float)			{ }
 JPH_IMPLEMENT_RTTI_OUTSIDE_CLASS(bool)			{ }
-JPH_IMPLEMENT_RTTI_OUTSIDE_CLASS(string)		{ }
+JPH_IMPLEMENT_RTTI_OUTSIDE_CLASS(String)		{ }
 JPH_IMPLEMENT_RTTI_OUTSIDE_CLASS(Float3)		{ }
 JPH_IMPLEMENT_RTTI_OUTSIDE_CLASS(Vec3)			{ }
 JPH_IMPLEMENT_RTTI_OUTSIDE_CLASS(Vec4)			{ }

+ 1 - 1
Jolt/ObjectStream/TypeDeclarations.h

@@ -18,7 +18,7 @@ JPH_DECLARE_RTTI_OUTSIDE_CLASS(uint32);
 JPH_DECLARE_RTTI_OUTSIDE_CLASS(uint64);
 JPH_DECLARE_RTTI_OUTSIDE_CLASS(float);
 JPH_DECLARE_RTTI_OUTSIDE_CLASS(bool);
-JPH_DECLARE_RTTI_OUTSIDE_CLASS(string);
+JPH_DECLARE_RTTI_OUTSIDE_CLASS(String);
 JPH_DECLARE_RTTI_OUTSIDE_CLASS(Float3);
 JPH_DECLARE_RTTI_OUTSIDE_CLASS(Vec3);
 JPH_DECLARE_RTTI_OUTSIDE_CLASS(Vec4);

+ 3 - 1
Jolt/Physics/Body/Body.cpp

@@ -16,17 +16,19 @@
 
 JPH_NAMESPACE_BEGIN
 
+static const SphereShape sFixedToWorldShape(FLT_EPSILON);
 Body Body::sFixedToWorld(false);
 
 Body::Body(bool) :
 	mPosition(Vec3::sZero()),
 	mRotation(Quat::sIdentity()),
-	mShape(new SphereShape(FLT_EPSILON)), // Dummy shape
+	mShape(&sFixedToWorldShape), // Dummy shape
 	mFriction(0.0f),
 	mRestitution(0.0f),
 	mObjectLayer(cObjectLayerInvalid),
 	mMotionType(EMotionType::Static)
 {
+	sFixedToWorldShape.SetEmbedded();
 }
 
 void Body::SetMotionType(EMotionType inMotionType)

+ 2 - 0
Jolt/Physics/Body/Body.h

@@ -31,6 +31,8 @@ class BodyCreationSettings;
 class Body : public NonCopyable
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Default constructor
 							Body() = default;
 

+ 2 - 2
Jolt/Physics/Body/BodyCreationSettings.h

@@ -57,8 +57,8 @@ public:
 	/// Restore the state of this object from inStream. Doesn't restore the shape nor the group filter.
 	void					RestoreBinaryState(StreamIn &inStream);
 
-	using GroupFilterToIDMap = unordered_map<const GroupFilter *, uint32>;
-	using IDToGroupFilterMap = vector<RefConst<GroupFilter>>;
+	using GroupFilterToIDMap = UnorderedMap<const GroupFilter *, uint32>;
+	using IDToGroupFilterMap = Array<RefConst<GroupFilter>>;
 	using ShapeToIDMap = Shape::ShapeToIDMap;
 	using IDToShapeMap = Shape::IDToShapeMap;
 	using MaterialToIDMap = Shape::MaterialToIDMap;

+ 1 - 1
Jolt/Physics/Body/BodyFilter.h

@@ -79,7 +79,7 @@ public:
 	}
 
 private:
-	vector<BodyID>			mBodyIDs;
+	Array<BodyID>			mBodyIDs;
 };
 
 JPH_NAMESPACE_END

+ 2 - 0
Jolt/Physics/Body/BodyID.h

@@ -11,6 +11,8 @@ JPH_NAMESPACE_BEGIN
 class BodyID
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	static constexpr uint32	cInvalidBodyID = 0xffffffff;	///< The value for an invalid body ID
 	static constexpr uint32	cBroadPhaseBit = 0x00800000;	///< This bit is used by the broadphase
 	static constexpr uint32	cMaxBodyIndex = 0x7fffff;		///< Maximum value for body index (also the maximum amount of bodies supported - 1)

+ 3 - 1
Jolt/Physics/Body/BodyManager.cpp

@@ -25,6 +25,8 @@ JPH_NAMESPACE_BEGIN
 class BodyWithMotionProperties : public Body
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	MotionProperties		mMotionProperties;
 };
 
@@ -718,7 +720,7 @@ void BodyManager::Draw(const DrawSettings &inDrawSettings, const PhysicsSettings
 			if (inDrawSettings.mDrawSleepStats && body->IsDynamic() && body->IsActive())
 			{
 				// Draw stats to know which bodies could go to sleep
-				string text = StringFormat("t: %.1f", (double)body->mMotionProperties->mSleepTestTimer);
+				String text = StringFormat("t: %.1f", (double)body->mMotionProperties->mSleepTestTimer);
 				uint8 g = uint8(Clamp(255.0f * body->mMotionProperties->mSleepTestTimer / inPhysicsSettings.mTimeBeforeSleep, 0.0f, 255.0f));
 				Color sleep_color = Color(0, 255 - g, g);
 				inRenderer->DrawText3D(body->GetCenterOfMassPosition(), text, sleep_color, 0.2f);

+ 5 - 3
Jolt/Physics/Body/BodyManager.h

@@ -18,15 +18,17 @@ class DebugRenderer;
 #endif // JPH_DEBUG_RENDERER
 
 /// Array of bodies
-using BodyVector = vector<Body *>;
+using BodyVector = Array<Body *>;
 
 /// Array of body ID's
-using BodyIDVector = vector<BodyID>;
+using BodyIDVector = Array<BodyID>;
 
 /// Class that contains all bodies
 class BodyManager : public NonCopyable
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Destructor
 									~BodyManager();
 
@@ -248,7 +250,7 @@ private:
 	mutable BodyMutexes				mBodyMutexes;
 
 	/// List of next sequence number for a body ID
-	vector<uint8>					mBodySequenceNumbers;
+	Array<uint8>					mBodySequenceNumbers;
 
 	/// Mutex that protects the mActiveBodies array
 	mutable Mutex					mActiveBodiesMutex;

+ 2 - 0
Jolt/Physics/Body/BodyPair.h

@@ -11,6 +11,8 @@ JPH_NAMESPACE_BEGIN
 /// Structure that holds a body pair
 struct BodyPair
 {
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Constructor
 							BodyPair() = default;
 							BodyPair(BodyID inA, BodyID inB)							: mBodyA(inA), mBodyB(inB) { }

+ 2 - 0
Jolt/Physics/Body/MotionProperties.h

@@ -17,6 +17,8 @@ class StateRecorder;
 class MotionProperties
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Motion quality, or how well it detects collisions when it has a high velocity
 	EMotionQuality			GetMotionQuality() const										{ return mMotionQuality; }
 	void					SetMotionQuality(EMotionQuality inQuality)						{ mMotionQuality = inQuality; }

+ 4 - 0
Jolt/Physics/Character/Character.h

@@ -12,6 +12,8 @@ JPH_NAMESPACE_BEGIN
 class CharacterSettings : public CharacterBaseSettings
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Layer that this character will be added to
 	ObjectLayer							mLayer = 0;
 
@@ -32,6 +34,8 @@ public:
 class Character : public CharacterBase
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Constructor
 	/// @param inSettings The settings for the character
 	/// @param inPosition Initial position for the character

+ 4 - 0
Jolt/Physics/Character/CharacterBase.h

@@ -19,6 +19,8 @@ class StateRecorder;
 class CharacterBaseSettings : public RefTarget<CharacterBaseSettings>
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Virtual destructor
 	virtual								~CharacterBaseSettings() = default;
 
@@ -34,6 +36,8 @@ public:
 class CharacterBase : public RefTarget<CharacterBase>, public NonCopyable
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Constructor
 										CharacterBase(const CharacterBaseSettings *inSettings, PhysicsSystem *inSystem);
 

+ 3 - 0
Jolt/Physics/Character/CharacterVirtual.cpp

@@ -8,6 +8,9 @@
 #include <Jolt/Physics/PhysicsSystem.h>
 #include <Jolt/Physics/Collision/ShapeCast.h>
 #include <Jolt/Physics/Collision/CollideShape.h>
+#ifdef JPH_DEBUG_RENDERER
+	#include <Jolt/Renderer/DebugRenderer.h>
+#endif // JPH_DEBUG_RENDERER
 
 JPH_NAMESPACE_BEGIN
 

+ 7 - 1
Jolt/Physics/Character/CharacterVirtual.h

@@ -18,6 +18,8 @@ class CharacterVirtual;
 class CharacterVirtualSettings : public CharacterBaseSettings
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Vector indicating the up direction of the character
 	Vec3								mUp = Vec3::sAxisY();
 
@@ -50,6 +52,8 @@ public:
 class CharacterContactListener
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Destructor
 	virtual								~CharacterContactListener() = default;
 
@@ -68,6 +72,8 @@ public:
 class CharacterVirtual : public CharacterBase
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Constructor
 	/// @param inSettings The settings for the character
 	/// @param inPosition Initial position for the character
@@ -195,7 +201,7 @@ private:
 	};
 
 	using TempContactList = vector<Contact, STLTempAllocator<Contact>>;
-	using ContactList = vector<Contact>;
+	using ContactList = Array<Contact>;
 
 	// A contact that needs to be ignored
 	struct IgnoredContact

+ 2 - 0
Jolt/Physics/Collision/AABoxCast.h

@@ -10,6 +10,8 @@ JPH_NAMESPACE_BEGIN
 /// Structure that holds AABox moving linearly through 3d space
 struct AABoxCast
 {
+	JPH_OVERRIDE_NEW_DELETE
+
 	AABox						mBox;						///< Axis aligned box at starting location
 	Vec3						mDirection;					///< Direction and length of the cast (anything beyond this length will not be reported as a hit)
 };

+ 1 - 1
Jolt/Physics/Collision/BroadPhase/BroadPhaseBruteForce.cpp

@@ -62,7 +62,7 @@ void BroadPhaseBruteForce::RemoveBodies(BodyID *ioBodies, int inNumber)
 		JPH_ASSERT(body.IsInBroadPhase());
 
 		// Find body id
-		vector<BodyID>::iterator it = lower_bound(mBodyIDs.begin(), mBodyIDs.end(), body.GetID());
+		Array<BodyID>::iterator it = lower_bound(mBodyIDs.begin(), mBodyIDs.end(), body.GetID());
 		JPH_ASSERT(it != mBodyIDs.end());
 
 		// Remove element

+ 3 - 1
Jolt/Physics/Collision/BroadPhase/BroadPhaseBruteForce.h

@@ -12,6 +12,8 @@ JPH_NAMESPACE_BEGIN
 class BroadPhaseBruteForce final : public BroadPhase
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	// Implementing interface of BroadPhase (see BroadPhase for documentation)
 	virtual void		AddBodiesFinalize(BodyID *ioBodies, int inNumber, AddState inAddState) override;
 	virtual void		RemoveBodies(BodyID *ioBodies, int inNumber) override;
@@ -27,7 +29,7 @@ public:
 	virtual void		FindCollidingPairs(BodyID *ioActiveBodies, int inNumActiveBodies, float inSpeculativeContactDistance, ObjectVsBroadPhaseLayerFilter inObjectVsBroadPhaseLayerFilter, ObjectLayerPairFilter inObjectLayerPairFilter, BodyPairCollector &ioPairCollector) const override;
 
 private:
-	vector<BodyID>		mBodyIDs;
+	Array<BodyID>		mBodyIDs;
 	mutable SharedMutex	mMutex;
 };
 

+ 4 - 0
Jolt/Physics/Collision/BroadPhase/BroadPhaseQuadTree.h

@@ -12,6 +12,8 @@ JPH_NAMESPACE_BEGIN
 class BroadPhaseQuadTree final : public BroadPhase
 {
 public:
+	JPH_OVERRIDE_NEW_DELETE
+
 	/// Destructor
 	virtual					~BroadPhaseQuadTree() override;
 
@@ -45,6 +47,8 @@ private:
 	/// Helper struct for AddBodies handle
 	struct LayerState
 	{
+		JPH_OVERRIDE_NEW_DELETE
+
 		BodyID *			mBodyStart = nullptr;
 		BodyID *			mBodyEnd;
 		QuadTree::AddState	mAddState;

+ 3 - 3
Jolt/Physics/Collision/BroadPhase/QuadTree.cpp

@@ -1549,7 +1549,7 @@ void QuadTree::DumpTree(const NodeID &inRoot, const char *inFileNamePrefix) cons
 		if (node_id.IsBody())
 		{
 			// Output body
-			string body_id = ConvertToString(node_id.GetBodyID().GetIndex());
+			String body_id = ConvertToString(node_id.GetBodyID().GetIndex());
 			f << "body" << body_id << "[label = \"Body " << body_id << "\"]\n";
 		}
 		else
@@ -1563,7 +1563,7 @@ void QuadTree::DumpTree(const NodeID &inRoot, const char *inFileNamePrefix) cons
 			node.GetNodeBounds(bounds);
 
 			// Output node
-			string node_str = ConvertToString(node_idx);
+			String node_str = ConvertToString(node_idx);
 			f << "node" << node_str << "[label = \"Node " << node_str << "\nVolume: " << ConvertToString(bounds.GetVolume()) << "\" color=" << (node.mIsChanged? "red" : "black") << "]\n";
 
 			// Recurse and get all children
@@ -1592,7 +1592,7 @@ void QuadTree::DumpTree(const NodeID &inRoot, const char *inFileNamePrefix) cons
 	f.close();
 
 	// Convert to svg file
-	string cmd = StringFormat("dot %s.dot -Tsvg -o %s.svg", inFileNamePrefix, inFileNamePrefix);
+	String cmd = StringFormat("dot %s.dot -Tsvg -o %s.svg", inFileNamePrefix, inFileNamePrefix);
 	system(cmd.c_str());
 }
 

+ 7 - 6
Jolt/Physics/Collision/BroadPhase/QuadTree.h

@@ -9,10 +9,6 @@
 #include <Jolt/Physics/Body/BodyManager.h>
 #include <Jolt/Physics/Collision/BroadPhase/BroadPhase.h>
 
-#ifdef JPH_TRACK_BROADPHASE_STATS
-	#include <map>
-#endif // JPH_TRACK_BROADPHASE_STATS
-
 //#define JPH_DUMP_BROADPHASE_TREE
 
 JPH_NAMESPACE_BEGIN
@@ -22,6 +18,9 @@ JPH_NAMESPACE_BEGIN
 /// During the UpdatePrepare/Finalize() call the tree is rebuilt to achieve a tight fit again.
 class QuadTree : public NonCopyable
 {
+public:
+	JPH_OVERRIDE_NEW_DELETE
+
 private:
 	// Forward declare
 	class AtomicNodeID;
@@ -30,6 +29,8 @@ private:
 	class NodeID
 	{
 	public:
+		JPH_OVERRIDE_NEW_DELETE
+
 		/// Default constructor does not initialize
 		inline 					NodeID() = default;
 
@@ -164,7 +165,7 @@ public:
 		atomic<uint32>			mBodyLocation { cInvalidBodyLocation };
 	};
 
-	using TrackingVector = vector<Tracking>;
+	using TrackingVector = Array<Tracking>;
 
 	/// Destructor
 								~QuadTree();
@@ -331,7 +332,7 @@ private:
 		uint64					mCollectorTicks = 0;
 	};
 	
-	using LayerToStats = map<string, Stat>;
+	using LayerToStats = UnorderedMap<String, Stat>;
 
 	/// Trace the stats of a single query type to the TTY
 	void						ReportStats(const char *inName, const LayerToStats &inLayer) const;

Some files were not shown because too many files changed in this diff