123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
- // SPDX-License-Identifier: MIT
- #pragma once
- #include <Jolt/Physics/Body/BodyLockInterface.h>
- JPH_NAMESPACE_BEGIN
- /// Base class for locking multiple bodies for the duration of the scope of this class (do not use directly)
- template <bool Write, class BodyType>
- 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<false, const Body>
- {
- using BodyLockMultiBase::BodyLockMultiBase;
- };
- /// Specialization that locks multiple bodies for writing to. @see BodyLockMultiRead for usage patterns.
- class BodyLockMultiWrite : public BodyLockMultiBase<true, Body>
- {
- using BodyLockMultiBase::BodyLockMultiBase;
- };
- JPH_NAMESPACE_END
|