Jolt Physics
A multi core friendly Game Physics Engine
Loading...
Searching...
No Matches
PhysicsLock.h
Go to the documentation of this file.
1// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3// SPDX-License-Identifier: MIT
4
5#pragma once
6
7#include <Jolt/Core/Mutex.h>
8
10
11#ifdef JPH_ENABLE_ASSERTS
12
14enum class EPhysicsLockTypes
15{
16 BroadPhaseQuery = 1 << 0,
17 PerBody = 1 << 1,
18 BodiesList = 1 << 2,
19 BroadPhaseUpdate = 1 << 3,
20 ConstraintsList = 1 << 4,
21 ActiveBodiesList = 1 << 5,
22};
23
25class BodyManager;
26using PhysicsLockContext = const BodyManager *;
27
28#endif // !JPH_ENABLE_ASSERTS
29
33{
34public:
35#ifdef JPH_ENABLE_ASSERTS
37 static inline void sCheckLock(PhysicsLockContext inContext, EPhysicsLockTypes inType)
38 {
39 uint32 &mutexes = sGetLockedMutexes(inContext);
40 JPH_ASSERT(uint32(inType) > mutexes, "A lock of same or higher priority was already taken, this can create a deadlock!");
41 mutexes = mutexes | uint32(inType);
42 }
43
45 static inline void sCheckUnlock(PhysicsLockContext inContext, EPhysicsLockTypes inType)
46 {
47 uint32 &mutexes = sGetLockedMutexes(inContext);
48 JPH_ASSERT((mutexes & uint32(inType)) != 0, "Mutex was not locked!");
49 mutexes = mutexes & ~uint32(inType);
50 }
51#endif // !JPH_ENABLE_ASSERTS
52
53 template <class LockType>
54 static inline void sLock(LockType &inMutex JPH_IF_ENABLE_ASSERTS(, PhysicsLockContext inContext, EPhysicsLockTypes inType))
55 {
56 JPH_IF_ENABLE_ASSERTS(sCheckLock(inContext, inType);)
57 inMutex.lock();
58 }
59
60 template <class LockType>
61 static inline void sUnlock(LockType &inMutex JPH_IF_ENABLE_ASSERTS(, PhysicsLockContext inContext, EPhysicsLockTypes inType))
62 {
63 JPH_IF_ENABLE_ASSERTS(sCheckUnlock(inContext, inType);)
64 inMutex.unlock();
65 }
66
67 template <class LockType>
68 static inline void sLockShared(LockType &inMutex JPH_IF_ENABLE_ASSERTS(, PhysicsLockContext inContext, EPhysicsLockTypes inType))
69 {
70 JPH_IF_ENABLE_ASSERTS(sCheckLock(inContext, inType);)
71 inMutex.lock_shared();
72 }
73
74 template <class LockType>
75 static inline void sUnlockShared(LockType &inMutex JPH_IF_ENABLE_ASSERTS(, PhysicsLockContext inContext, EPhysicsLockTypes inType))
76 {
77 JPH_IF_ENABLE_ASSERTS(sCheckUnlock(inContext, inType);)
78 inMutex.unlock_shared();
79 }
80
81#ifdef JPH_ENABLE_ASSERTS
82private:
83 struct LockData
84 {
85 uint32 mLockedMutexes = 0;
86 PhysicsLockContext mContext = nullptr;
87 };
88
89 static thread_local LockData sLocks[4];
90
91 // Helper function to find the locked mutexes for a particular context
92 static uint32 & sGetLockedMutexes(PhysicsLockContext inContext)
93 {
94 // If we find a matching context we can use it
95 for (LockData &l : sLocks)
96 if (l.mContext == inContext)
97 return l.mLockedMutexes;
98
99 // Otherwise we look for an entry that is not in use
100 for (LockData &l : sLocks)
101 if (l.mLockedMutexes == 0)
102 {
103 l.mContext = inContext;
104 return l.mLockedMutexes;
105 }
106
107 JPH_ASSERT(false, "Too many physics systems locked at the same time!");
108 return sLocks[0].mLockedMutexes;
109 }
110#endif // !JPH_ENABLE_ASSERTS
111};
112
114template <class LockType>
116{
117public:
118 explicit UniqueLock(LockType &inLock JPH_IF_ENABLE_ASSERTS(, PhysicsLockContext inContext, EPhysicsLockTypes inType)) :
119 mLock(inLock)
120#ifdef JPH_ENABLE_ASSERTS
121 , mContext(inContext),
122 mType(inType)
123#endif // JPH_ENABLE_ASSERTS
124 {
125 PhysicsLock::sLock(mLock JPH_IF_ENABLE_ASSERTS(, mContext, mType));
126 }
127
129 {
130 PhysicsLock::sUnlock(mLock JPH_IF_ENABLE_ASSERTS(, mContext, mType));
131 }
132
133private:
134 LockType & mLock;
135#ifdef JPH_ENABLE_ASSERTS
136 PhysicsLockContext mContext;
137 EPhysicsLockTypes mType;
138#endif // JPH_ENABLE_ASSERTS
139};
140
142template <class LockType>
144{
145public:
146 explicit SharedLock(LockType &inLock JPH_IF_ENABLE_ASSERTS(, PhysicsLockContext inContext, EPhysicsLockTypes inType)) :
147 mLock(inLock)
148#ifdef JPH_ENABLE_ASSERTS
149 , mContext(inContext)
150 , mType(inType)
151#endif // JPH_ENABLE_ASSERTS
152 {
153 PhysicsLock::sLockShared(mLock JPH_IF_ENABLE_ASSERTS(, mContext, mType));
154 }
155
157 {
158 PhysicsLock::sUnlockShared(mLock JPH_IF_ENABLE_ASSERTS(, mContext, mType));
159 }
160
161private:
162 LockType & mLock;
163#ifdef JPH_ENABLE_ASSERTS
164 PhysicsLockContext mContext;
165 EPhysicsLockTypes mType;
166#endif // JPH_ENABLE_ASSERTS
167};
168
#define JPH_NAMESPACE_END
Definition: Core.h:367
std::uint32_t uint32
Definition: Core.h:442
#define JPH_NAMESPACE_BEGIN
Definition: Core.h:361
#define JPH_IF_ENABLE_ASSERTS(...)
Definition: IssueReporting.h:35
#define JPH_ASSERT(...)
Definition: IssueReporting.h:33
Class that contains all bodies.
Definition: BodyManager.h:32
Definition: BroadPhaseQuery.h:29
Class that makes another class non-copyable. Usage: Inherit from NonCopyable.
Definition: NonCopyable.h:11
Definition: PhysicsLock.h:33
static void sLockShared(LockType &inMutex JPH_IF_ENABLE_ASSERTS(, PhysicsLockContext inContext, EPhysicsLockTypes inType))
Definition: PhysicsLock.h:68
static void sUnlock(LockType &inMutex JPH_IF_ENABLE_ASSERTS(, PhysicsLockContext inContext, EPhysicsLockTypes inType))
Definition: PhysicsLock.h:61
static void sUnlockShared(LockType &inMutex JPH_IF_ENABLE_ASSERTS(, PhysicsLockContext inContext, EPhysicsLockTypes inType))
Definition: PhysicsLock.h:75
static void sLock(LockType &inMutex JPH_IF_ENABLE_ASSERTS(, PhysicsLockContext inContext, EPhysicsLockTypes inType))
Definition: PhysicsLock.h:54
Helper class that is similar to std::shared_lock.
Definition: PhysicsLock.h:144
SharedLock(LockType &inLock JPH_IF_ENABLE_ASSERTS(, PhysicsLockContext inContext, EPhysicsLockTypes inType))
Definition: PhysicsLock.h:146
~SharedLock()
Definition: PhysicsLock.h:156
Helper class that is similar to std::unique_lock.
Definition: PhysicsLock.h:116
UniqueLock(LockType &inLock JPH_IF_ENABLE_ASSERTS(, PhysicsLockContext inContext, EPhysicsLockTypes inType))
Definition: PhysicsLock.h:118
~UniqueLock()
Definition: PhysicsLock.h:128