MutexArray.h 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #pragma once
  5. #include <Jolt/Core/NonCopyable.h>
  6. JPH_NAMESPACE_BEGIN
  7. /// A mutex array protects a number of resources with a limited amount of mutexes.
  8. /// It uses hashing to find the mutex of a particular object.
  9. /// The idea is that if the amount of threads is much smaller than the amount of mutexes
  10. /// that there is a relatively small chance that two different objects map to the same mutex.
  11. template <class MutexType>
  12. class MutexArray : public NonCopyable
  13. {
  14. public:
  15. /// Constructor, constructs an empty mutex array that you need to initialize with Init()
  16. MutexArray() = default;
  17. /// Constructor, constructs an array with inNumMutexes entries
  18. explicit MutexArray(uint inNumMutexes) { Init(inNumMutexes); }
  19. /// Destructor
  20. ~MutexArray() { delete [] mMutexStorage; }
  21. /// Initialization
  22. /// @param inNumMutexes The amount of mutexes to allocate
  23. void Init(uint inNumMutexes)
  24. {
  25. JPH_ASSERT(mMutexStorage == nullptr);
  26. JPH_ASSERT(inNumMutexes > 0 && IsPowerOf2(inNumMutexes));
  27. mMutexStorage = new MutexStorage[inNumMutexes];
  28. mNumMutexes = inNumMutexes;
  29. }
  30. /// Get the number of mutexes that were allocated
  31. inline uint GetNumMutexes() const
  32. {
  33. return mNumMutexes;
  34. }
  35. /// Convert an object index to a mutex index
  36. inline uint32 GetMutexIndex(uint32 inObjectIndex) const
  37. {
  38. std::hash<uint32> hasher;
  39. return hasher(inObjectIndex) & (mNumMutexes - 1);
  40. }
  41. /// Get the mutex belonging to a certain object by index
  42. inline MutexType & GetMutexByObjectIndex(uint32 inObjectIndex)
  43. {
  44. return mMutexStorage[GetMutexIndex(inObjectIndex)].mMutex;
  45. }
  46. /// Get a mutex by index in the array
  47. inline MutexType & GetMutexByIndex(uint32 inMutexIndex)
  48. {
  49. return mMutexStorage[inMutexIndex].mMutex;
  50. }
  51. /// Lock all mutexes
  52. void LockAll()
  53. {
  54. JPH_PROFILE_FUNCTION();
  55. MutexStorage *end = mMutexStorage + mNumMutexes;
  56. for (MutexStorage *m = mMutexStorage; m < end; ++m)
  57. m->mMutex.lock();
  58. }
  59. /// Unlock all mutexes
  60. void UnlockAll()
  61. {
  62. JPH_PROFILE_FUNCTION();
  63. MutexStorage *end = mMutexStorage + mNumMutexes;
  64. for (MutexStorage *m = mMutexStorage; m < end; ++m)
  65. m->mMutex.unlock();
  66. }
  67. private:
  68. /// Align the mutex to a cache line to ensure there is no false sharing (this is platform dependent, we do this to be safe)
  69. struct alignas(JPH_CACHE_LINE_SIZE) MutexStorage
  70. {
  71. JPH_OVERRIDE_NEW_DELETE
  72. MutexType mMutex;
  73. };
  74. MutexStorage * mMutexStorage = nullptr;
  75. uint mNumMutexes = 0;
  76. };
  77. JPH_NAMESPACE_END