// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics) // SPDX-FileCopyrightText: 2021 Jorrit Rouwe // SPDX-License-Identifier: MIT #pragma once #include JPH_NAMESPACE_BEGIN /// Base class for locking multiple bodies for the duration of the scope of this class (do not use directly) template class BodyLockMultiBase : public NonCopyable { public: /// Redefine MutexMask using MutexMask = BodyLockInterface::MutexMask; /// Constructor will lock the bodies BodyLockMultiBase(const BodyLockInterface &inBodyLockInterface, const BodyID *inBodyIDs, int inNumber) : mBodyLockInterface(inBodyLockInterface), mMutexMask(inBodyLockInterface.GetMutexMask(inBodyIDs, inNumber)), mBodyIDs(inBodyIDs), mNumBodyIDs(inNumber) { if (mMutexMask != 0) { // Get mutex if (Write) inBodyLockInterface.LockWrite(mMutexMask); else inBodyLockInterface.LockRead(mMutexMask); } } /// Destructor will unlock the bodies ~BodyLockMultiBase() { if (mMutexMask != 0) { if (Write) mBodyLockInterface.UnlockWrite(mMutexMask); else mBodyLockInterface.UnlockRead(mMutexMask); } } /// Access the body (returns null if body was not properly locked) inline BodyType * GetBody(int inBodyIndex) const { // Range check JPH_ASSERT(inBodyIndex >= 0 && inBodyIndex < mNumBodyIDs); // Get body ID const BodyID &body_id = mBodyIDs[inBodyIndex]; if (body_id.IsInvalid()) return nullptr; // Get a reference to the body or nullptr when it is no longer valid return mBodyLockInterface.TryGetBody(body_id); } private: const BodyLockInterface & mBodyLockInterface; MutexMask mMutexMask; const BodyID * mBodyIDs; int mNumBodyIDs; }; /// A multi body lock takes a number of body IDs and locks the underlying bodies so that other threads cannot access its members /// /// The common usage pattern is: /// /// BodyLockInterface lock_interface = physics_system.GetBodyLockInterface(); // Or non-locking interface if the lock is already taken /// const BodyID *body_id = ...; // Obtain IDs to bodies /// int num_body_ids = ...; /// /// // Scoped lock /// { /// BodyLockMultiRead lock(lock_interface, body_ids, num_body_ids); /// for (int i = 0; i < num_body_ids; ++i) /// { /// const Body *body = lock.GetBody(i); /// if (body != nullptr) /// { /// const Body &body = lock.Body(); /// /// // Do something with body /// ... /// } /// } /// } class BodyLockMultiRead : public BodyLockMultiBase { using BodyLockMultiBase::BodyLockMultiBase; }; /// Specialization that locks multiple bodies for writing to. @see BodyLockMultiRead for usage patterns. class BodyLockMultiWrite : public BodyLockMultiBase { using BodyLockMultiBase::BodyLockMultiBase; }; JPH_NAMESPACE_END