TempAllocator.h 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. namespace JPH {
  5. /// Allocator for temporary allocations.
  6. /// This allocator works as a stack: The blocks must always be freed in the reverse order as they are allocated.
  7. /// Note that allocations and frees can take place from different threads, but the order is guaranteed though
  8. /// job dependencies, so it is not needed to use any form of locking.
  9. class TempAllocator
  10. {
  11. public:
  12. /// Destructor
  13. virtual ~TempAllocator() = default;
  14. /// Allocates inSize bytes of memory, returned memory address must be 16 byte aligned
  15. virtual void * Allocate(uint inSize) = 0;
  16. /// Frees inSize bytes of memory located at inAddress
  17. virtual void Free(void *inAddress, uint inSize) = 0;
  18. };
  19. /// Default implementation of the temp allocator that allocates a large block through malloc upfront
  20. class TempAllocatorImpl final : public TempAllocator
  21. {
  22. public:
  23. /// Constructs the allocator with a maximum allocatable size of inSize
  24. explicit TempAllocatorImpl(uint inSize) :
  25. mBase(static_cast<uint8 *>(malloc(inSize))),
  26. mSize(inSize)
  27. {
  28. }
  29. /// Destructor, frees the block
  30. virtual ~TempAllocatorImpl() override
  31. {
  32. JPH_ASSERT(mTop == 0);
  33. free(mBase);
  34. }
  35. // See: TempAllocator
  36. virtual void * Allocate(uint inSize) override
  37. {
  38. if (inSize == 0)
  39. {
  40. return nullptr;
  41. }
  42. else
  43. {
  44. uint new_top = mTop + AlignUp(inSize, 16);
  45. if (new_top > mSize)
  46. JPH_CRASH; // Out of memory
  47. void *address = mBase + mTop;
  48. mTop = new_top;
  49. return address;
  50. }
  51. }
  52. // See: TempAllocator
  53. virtual void Free(void *inAddress, uint inSize) override
  54. {
  55. if (inAddress == nullptr)
  56. {
  57. JPH_ASSERT(inSize == 0);
  58. }
  59. else
  60. {
  61. mTop -= AlignUp(inSize, 16);
  62. if (mBase + mTop != inAddress)
  63. JPH_CRASH; // Freeing in the wrong order
  64. }
  65. }
  66. private:
  67. uint8 * mBase; ///< Base address of the memory block
  68. uint mSize; ///< Size of the memory block
  69. uint mTop = 0; ///< Current top of the stack
  70. };
  71. /// Implementation of the TempAllocator that just falls back to malloc/free
  72. /// Note: This can be quite slow when running in the debugger as large memory blocks need to be initialized with 0xcd
  73. class TempAllocatorMalloc final : public TempAllocator
  74. {
  75. public:
  76. // See: TempAllocator
  77. virtual void * Allocate(uint inSize) override
  78. {
  79. return malloc(inSize);
  80. }
  81. // See: TempAllocator
  82. virtual void Free(void *inAddress, uint inSize) override
  83. {
  84. free(inAddress);
  85. }
  86. };
  87. }; // JPH