Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Core/Mutex.h
9906 views
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/Profiler.h>
8
#include <Jolt/Core/NonCopyable.h>
9
10
JPH_SUPPRESS_WARNINGS_STD_BEGIN
11
#include <mutex>
12
#include <shared_mutex>
13
#include <thread>
14
JPH_SUPPRESS_WARNINGS_STD_END
15
16
JPH_NAMESPACE_BEGIN
17
18
// Things we're using from STL
19
using std::mutex;
20
using std::shared_mutex;
21
using std::thread;
22
using std::lock_guard;
23
using std::shared_lock;
24
using std::unique_lock;
25
26
#ifdef JPH_PLATFORM_BLUE
27
28
// On Platform Blue the mutex class is not very fast so we implement it using the official APIs
29
class MutexBase : public NonCopyable
30
{
31
public:
32
MutexBase()
33
{
34
JPH_PLATFORM_BLUE_MUTEX_INIT(mMutex);
35
}
36
37
~MutexBase()
38
{
39
JPH_PLATFORM_BLUE_MUTEX_DESTROY(mMutex);
40
}
41
42
inline bool try_lock()
43
{
44
return JPH_PLATFORM_BLUE_MUTEX_TRYLOCK(mMutex);
45
}
46
47
inline void lock()
48
{
49
JPH_PLATFORM_BLUE_MUTEX_LOCK(mMutex);
50
}
51
52
inline void unlock()
53
{
54
JPH_PLATFORM_BLUE_MUTEX_UNLOCK(mMutex);
55
}
56
57
private:
58
JPH_PLATFORM_BLUE_MUTEX mMutex;
59
};
60
61
// On Platform Blue the shared_mutex class is not very fast so we implement it using the official APIs
62
class SharedMutexBase : public NonCopyable
63
{
64
public:
65
SharedMutexBase()
66
{
67
JPH_PLATFORM_BLUE_RWLOCK_INIT(mRWLock);
68
}
69
70
~SharedMutexBase()
71
{
72
JPH_PLATFORM_BLUE_RWLOCK_DESTROY(mRWLock);
73
}
74
75
inline bool try_lock()
76
{
77
return JPH_PLATFORM_BLUE_RWLOCK_TRYWLOCK(mRWLock);
78
}
79
80
inline bool try_lock_shared()
81
{
82
return JPH_PLATFORM_BLUE_RWLOCK_TRYRLOCK(mRWLock);
83
}
84
85
inline void lock()
86
{
87
JPH_PLATFORM_BLUE_RWLOCK_WLOCK(mRWLock);
88
}
89
90
inline void unlock()
91
{
92
JPH_PLATFORM_BLUE_RWLOCK_WUNLOCK(mRWLock);
93
}
94
95
inline void lock_shared()
96
{
97
JPH_PLATFORM_BLUE_RWLOCK_RLOCK(mRWLock);
98
}
99
100
inline void unlock_shared()
101
{
102
JPH_PLATFORM_BLUE_RWLOCK_RUNLOCK(mRWLock);
103
}
104
105
private:
106
JPH_PLATFORM_BLUE_RWLOCK mRWLock;
107
};
108
109
#else
110
111
// On other platforms just use the STL implementation
112
using MutexBase = mutex;
113
using SharedMutexBase = shared_mutex;
114
115
#endif // JPH_PLATFORM_BLUE
116
117
#if defined(JPH_ENABLE_ASSERTS) || defined(JPH_PROFILE_ENABLED) || defined(JPH_EXTERNAL_PROFILE)
118
119
/// Very simple wrapper around MutexBase which tracks lock contention in the profiler
120
/// and asserts that locks/unlocks take place on the same thread
121
class Mutex : public MutexBase
122
{
123
public:
124
inline bool try_lock()
125
{
126
JPH_ASSERT(mLockedThreadID != std::this_thread::get_id());
127
if (MutexBase::try_lock())
128
{
129
JPH_IF_ENABLE_ASSERTS(mLockedThreadID = std::this_thread::get_id();)
130
return true;
131
}
132
return false;
133
}
134
135
inline void lock()
136
{
137
if (!try_lock())
138
{
139
JPH_PROFILE("Lock", 0xff00ffff);
140
MutexBase::lock();
141
JPH_IF_ENABLE_ASSERTS(mLockedThreadID = std::this_thread::get_id();)
142
}
143
}
144
145
inline void unlock()
146
{
147
JPH_ASSERT(mLockedThreadID == std::this_thread::get_id());
148
JPH_IF_ENABLE_ASSERTS(mLockedThreadID = thread::id();)
149
MutexBase::unlock();
150
}
151
152
#ifdef JPH_ENABLE_ASSERTS
153
inline bool is_locked()
154
{
155
return mLockedThreadID != thread::id();
156
}
157
#endif // JPH_ENABLE_ASSERTS
158
159
private:
160
JPH_IF_ENABLE_ASSERTS(thread::id mLockedThreadID;)
161
};
162
163
/// Very simple wrapper around SharedMutexBase which tracks lock contention in the profiler
164
/// and asserts that locks/unlocks take place on the same thread
165
class SharedMutex : public SharedMutexBase
166
{
167
public:
168
inline bool try_lock()
169
{
170
JPH_ASSERT(mLockedThreadID != std::this_thread::get_id());
171
if (SharedMutexBase::try_lock())
172
{
173
JPH_IF_ENABLE_ASSERTS(mLockedThreadID = std::this_thread::get_id();)
174
return true;
175
}
176
return false;
177
}
178
179
inline void lock()
180
{
181
if (!try_lock())
182
{
183
JPH_PROFILE("WLock", 0xff00ffff);
184
SharedMutexBase::lock();
185
JPH_IF_ENABLE_ASSERTS(mLockedThreadID = std::this_thread::get_id();)
186
}
187
}
188
189
inline void unlock()
190
{
191
JPH_ASSERT(mLockedThreadID == std::this_thread::get_id());
192
JPH_IF_ENABLE_ASSERTS(mLockedThreadID = thread::id();)
193
SharedMutexBase::unlock();
194
}
195
196
#ifdef JPH_ENABLE_ASSERTS
197
inline bool is_locked()
198
{
199
return mLockedThreadID != thread::id();
200
}
201
#endif // JPH_ENABLE_ASSERTS
202
203
inline void lock_shared()
204
{
205
if (!try_lock_shared())
206
{
207
JPH_PROFILE("RLock", 0xff00ffff);
208
SharedMutexBase::lock_shared();
209
}
210
}
211
212
private:
213
JPH_IF_ENABLE_ASSERTS(thread::id mLockedThreadID;)
214
};
215
216
#else
217
218
using Mutex = MutexBase;
219
using SharedMutex = SharedMutexBase;
220
221
#endif
222
223
JPH_NAMESPACE_END
224
225