godot-module-template/engine/thirdparty/jolt_physics/Jolt/Physics/Body/BodyLockMulti.h

105 lines
2.8 KiB
C++

// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
// 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