Jolt Physics
A multi core friendly Game Physics Engine
Loading...
Searching...
No Matches
Mutex.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
9
11#include <atomic>
12#include <mutex>
13#include <shared_mutex>
14#include <thread>
16
18
19// Things we're using from STL
20using std::atomic;
21using std::mutex;
22using std::shared_mutex;
23using std::thread;
24using std::lock_guard;
25using std::shared_lock;
26using std::unique_lock;
27
28#ifdef JPH_PLATFORM_BLUE
29
30// On Platform Blue the mutex class is not very fast so we implement it using the official APIs
31class MutexBase : public NonCopyable
32{
33public:
34 MutexBase()
35 {
36 JPH_PLATFORM_BLUE_MUTEX_INIT(mMutex);
37 }
38
40 {
41 JPH_PLATFORM_BLUE_MUTEX_DESTROY(mMutex);
42 }
43
44 inline bool try_lock()
45 {
46 return JPH_PLATFORM_BLUE_MUTEX_TRYLOCK(mMutex);
47 }
48
49 inline void lock()
50 {
51 JPH_PLATFORM_BLUE_MUTEX_LOCK(mMutex);
52 }
53
54 inline void unlock()
55 {
56 JPH_PLATFORM_BLUE_MUTEX_UNLOCK(mMutex);
57 }
58
59private:
60 JPH_PLATFORM_BLUE_MUTEX mMutex;
61};
62
63// On Platform Blue the shared_mutex class is not very fast so we implement it using the official APIs
64class SharedMutexBase : public NonCopyable
65{
66public:
68 {
69 JPH_PLATFORM_BLUE_RWLOCK_INIT(mRWLock);
70 }
71
73 {
74 JPH_PLATFORM_BLUE_RWLOCK_DESTROY(mRWLock);
75 }
76
77 inline bool try_lock()
78 {
79 return JPH_PLATFORM_BLUE_RWLOCK_TRYWLOCK(mRWLock);
80 }
81
82 inline bool try_lock_shared()
83 {
84 return JPH_PLATFORM_BLUE_RWLOCK_TRYRLOCK(mRWLock);
85 }
86
87 inline void lock()
88 {
89 JPH_PLATFORM_BLUE_RWLOCK_WLOCK(mRWLock);
90 }
91
92 inline void unlock()
93 {
94 JPH_PLATFORM_BLUE_RWLOCK_WUNLOCK(mRWLock);
95 }
96
97 inline void lock_shared()
98 {
99 JPH_PLATFORM_BLUE_RWLOCK_RLOCK(mRWLock);
100 }
101
102 inline void unlock_shared()
103 {
104 JPH_PLATFORM_BLUE_RWLOCK_RUNLOCK(mRWLock);
105 }
106
107private:
108 JPH_PLATFORM_BLUE_RWLOCK mRWLock;
109};
110
111#else
112
113// On other platforms just use the STL implementation
114using MutexBase = mutex;
115using SharedMutexBase = shared_mutex;
116
117#endif // JPH_PLATFORM_BLUE
118
119#if defined(JPH_ENABLE_ASSERTS) || defined(JPH_PROFILE_ENABLED) || defined(JPH_EXTERNAL_PROFILE)
120
123class Mutex : public MutexBase
124{
125public:
126 inline bool try_lock()
127 {
128 JPH_ASSERT(mLockedThreadID.load(std::memory_order_relaxed) != std::this_thread::get_id());
129 if (MutexBase::try_lock())
130 {
131 JPH_IF_ENABLE_ASSERTS(mLockedThreadID.store(std::this_thread::get_id(), std::memory_order_relaxed);)
132 return true;
133 }
134 return false;
135 }
136
137 inline void lock()
138 {
139 if (!try_lock())
140 {
141 JPH_PROFILE("Lock", 0xff00ffff);
142 MutexBase::lock();
143 JPH_IF_ENABLE_ASSERTS(mLockedThreadID.store(std::this_thread::get_id(), std::memory_order_relaxed);)
144 }
145 }
146
147 inline void unlock()
148 {
149 JPH_ASSERT(mLockedThreadID.load(std::memory_order_relaxed) == std::this_thread::get_id());
150 JPH_IF_ENABLE_ASSERTS(mLockedThreadID.store(thread::id(), std::memory_order_relaxed);)
151 MutexBase::unlock();
152 }
153
154#ifdef JPH_ENABLE_ASSERTS
155 inline bool is_locked()
156 {
157 return mLockedThreadID.load(std::memory_order_relaxed) != thread::id();
158 }
159#endif // JPH_ENABLE_ASSERTS
160
161private:
162 JPH_IF_ENABLE_ASSERTS(atomic<thread::id> mLockedThreadID { };)
163};
164
168{
169public:
170 inline bool try_lock()
171 {
172 JPH_ASSERT(mLockedThreadID.load(std::memory_order_relaxed) != std::this_thread::get_id());
173 if (SharedMutexBase::try_lock())
174 {
175 JPH_IF_ENABLE_ASSERTS(mLockedThreadID.store(std::this_thread::get_id(), std::memory_order_relaxed);)
176 return true;
177 }
178 return false;
179 }
180
181 inline void lock()
182 {
183 if (!try_lock())
184 {
185 JPH_PROFILE("WLock", 0xff00ffff);
186 SharedMutexBase::lock();
187 JPH_IF_ENABLE_ASSERTS(mLockedThreadID.store(std::this_thread::get_id(), std::memory_order_relaxed);)
188 }
189 }
190
191 inline void unlock()
192 {
193 JPH_ASSERT(mLockedThreadID.load(std::memory_order_relaxed) == std::this_thread::get_id());
194 JPH_IF_ENABLE_ASSERTS(mLockedThreadID.store(thread::id(), std::memory_order_relaxed);)
195 SharedMutexBase::unlock();
196 }
197
198#ifdef JPH_ENABLE_ASSERTS
199 inline bool is_locked()
200 {
201 return mLockedThreadID.load(std::memory_order_relaxed) != thread::id();
202 }
203#endif // JPH_ENABLE_ASSERTS
204
205 inline void lock_shared()
206 {
207 if (!try_lock_shared())
208 {
209 JPH_PROFILE("RLock", 0xff00ffff);
210 SharedMutexBase::lock_shared();
211 }
212 }
213
214private:
215 JPH_IF_ENABLE_ASSERTS(atomic<thread::id> mLockedThreadID { };)
216};
217
218#else
219
220using Mutex = MutexBase;
222
223#endif
224
#define JPH_SUPPRESS_WARNINGS_STD_BEGIN
Definition Core.h:492
#define JPH_SUPPRESS_WARNINGS_STD_END
Definition Core.h:506
#define JPH_NAMESPACE_END
Definition Core.h:487
#define JPH_NAMESPACE_BEGIN
Definition Core.h:481
#define JPH_IF_ENABLE_ASSERTS(...)
Definition IssueReporting.h:30
#define JPH_ASSERT(...)
Definition IssueReporting.h:28
shared_mutex SharedMutexBase
Definition Mutex.h:115
mutex MutexBase
Definition Mutex.h:114
#define JPH_PROFILE(...)
Definition Profiler.h:267
Definition Mutex.h:124
void unlock()
Definition Mutex.h:147
bool try_lock()
Definition Mutex.h:126
void lock()
Definition Mutex.h:137
Class that makes another class non-copyable. Usage: Inherit from NonCopyable.
Definition NonCopyable.h:11
Definition Mutex.h:168
void lock_shared()
Definition Mutex.h:205
void unlock()
Definition Mutex.h:191
void lock()
Definition Mutex.h:181
bool try_lock()
Definition Mutex.h:170