BodyLock.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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/Physics/Body/BodyLockInterface.h>
  6. JPH_NAMESPACE_BEGIN
  7. /// Base class for locking bodies for the duration of the scope of this class (do not use directly)
  8. template <bool Write, class BodyType>
  9. class BodyLockBase : public NonCopyable
  10. {
  11. public:
  12. /// Constructor will lock the body
  13. BodyLockBase(const BodyLockInterface &inBodyLockInterface, const BodyID &inBodyID) :
  14. mBodyLockInterface(inBodyLockInterface)
  15. {
  16. if (inBodyID == BodyID())
  17. {
  18. // Invalid body id
  19. mBodyLockMutex = nullptr;
  20. mBody = nullptr;
  21. }
  22. else
  23. {
  24. // Get mutex
  25. mBodyLockMutex = Write? inBodyLockInterface.LockWrite(inBodyID) : inBodyLockInterface.LockRead(inBodyID);
  26. // Get a reference to the body or nullptr when it is no longer valid
  27. mBody = inBodyLockInterface.TryGetBody(inBodyID);
  28. }
  29. }
  30. /// Explicitly release the lock (normally this is done in the destructor)
  31. inline void ReleaseLock()
  32. {
  33. if (mBodyLockMutex != nullptr)
  34. {
  35. if (Write)
  36. mBodyLockInterface.UnlockWrite(mBodyLockMutex);
  37. else
  38. mBodyLockInterface.UnlockRead(mBodyLockMutex);
  39. mBodyLockMutex = nullptr;
  40. mBody = nullptr;
  41. }
  42. }
  43. /// Destructor will unlock the body
  44. ~BodyLockBase()
  45. {
  46. ReleaseLock();
  47. }
  48. /// Test if the lock was successful (if the body ID was valid)
  49. inline bool Succeeded() const
  50. {
  51. return mBody != nullptr;
  52. }
  53. /// Test if the lock was successful (if the body ID was valid) and the body is still in the broad phase
  54. inline bool SucceededAndIsInBroadPhase() const
  55. {
  56. return mBody != nullptr && mBody->IsInBroadPhase();
  57. }
  58. /// Access the body
  59. inline BodyType & GetBody() const
  60. {
  61. JPH_ASSERT(mBody != nullptr, "Should check Succeeded() first");
  62. return *mBody;
  63. }
  64. private:
  65. const BodyLockInterface & mBodyLockInterface;
  66. SharedMutex * mBodyLockMutex;
  67. BodyType * mBody;
  68. };
  69. /// A body lock takes a body ID and locks the underlying body so that other threads cannot access its members
  70. ///
  71. /// The common usage pattern is:
  72. ///
  73. /// BodyLockInterface lock_interface = physics_system.GetBodyLockInterface(); // Or non-locking interface if the lock is already taken
  74. /// BodyID body_id = ...; // Obtain ID to body
  75. ///
  76. /// // Scoped lock
  77. /// {
  78. /// BodyLockRead lock(lock_interface, body_id);
  79. /// if (lock.Succeeded()) // body_id may no longer be valid
  80. /// {
  81. /// const Body &body = lock.GetBody();
  82. ///
  83. /// // Do something with body
  84. /// ...
  85. /// }
  86. /// }
  87. class BodyLockRead : public BodyLockBase<false, const Body>
  88. {
  89. using BodyLockBase::BodyLockBase;
  90. };
  91. /// Specialization that locks a body for writing to. @see BodyLockRead for usage patterns.
  92. class BodyLockWrite : public BodyLockBase<true, Body>
  93. {
  94. using BodyLockBase::BodyLockBase;
  95. };
  96. JPH_NAMESPACE_END