MutexArray.h 2.5 KB

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