summaryrefslogtreecommitdiffstats
path: root/core/os/safe_binary_mutex.h
diff options
context:
space:
mode:
Diffstat (limited to 'core/os/safe_binary_mutex.h')
-rw-r--r--core/os/safe_binary_mutex.h95
1 files changed, 62 insertions, 33 deletions
diff --git a/core/os/safe_binary_mutex.h b/core/os/safe_binary_mutex.h
index 1e98cc074c..74a20043a3 100644
--- a/core/os/safe_binary_mutex.h
+++ b/core/os/safe_binary_mutex.h
@@ -37,6 +37,11 @@
#ifdef THREADS_ENABLED
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wundefined-var-template"
+#endif
+
// A very special kind of mutex, used in scenarios where these
// requirements hold at the same time:
// - Must be used with a condition variable (only binary mutexes are suitable).
@@ -47,69 +52,90 @@
// Also, don't forget to declare the thread_local variable on each use.
template <int Tag>
class SafeBinaryMutex {
- friend class MutexLock<SafeBinaryMutex>;
+ friend class MutexLock<SafeBinaryMutex<Tag>>;
using StdMutexType = THREADING_NAMESPACE::mutex;
mutable THREADING_NAMESPACE::mutex mutex;
- static thread_local uint32_t count;
+
+ struct TLSData {
+ mutable THREADING_NAMESPACE::unique_lock<THREADING_NAMESPACE::mutex> lock;
+ uint32_t count = 0;
+
+ TLSData(SafeBinaryMutex<Tag> &p_mutex) :
+ lock(p_mutex.mutex, THREADING_NAMESPACE::defer_lock) {}
+ };
+ static thread_local TLSData tls_data;
public:
_ALWAYS_INLINE_ void lock() const {
- if (++count == 1) {
- mutex.lock();
+ if (++tls_data.count == 1) {
+ tls_data.lock.lock();
}
}
_ALWAYS_INLINE_ void unlock() const {
- DEV_ASSERT(count);
- if (--count == 0) {
- mutex.unlock();
+ DEV_ASSERT(tls_data.count);
+ if (--tls_data.count == 0) {
+ tls_data.lock.unlock();
}
}
- _ALWAYS_INLINE_ bool try_lock() const {
- if (count) {
- count++;
- return true;
- } else {
- if (mutex.try_lock()) {
- count++;
- return true;
- } else {
- return false;
- }
- }
+ _ALWAYS_INLINE_ THREADING_NAMESPACE::unique_lock<THREADING_NAMESPACE::mutex> &_get_lock() const {
+ return const_cast<THREADING_NAMESPACE::unique_lock<THREADING_NAMESPACE::mutex> &>(tls_data.lock);
+ }
+
+ _ALWAYS_INLINE_ SafeBinaryMutex() {
}
- ~SafeBinaryMutex() {
- DEV_ASSERT(!count);
+ _ALWAYS_INLINE_ ~SafeBinaryMutex() {
+ DEV_ASSERT(!tls_data.count);
}
};
-// This specialization is needed so manual locking and MutexLock can be used
-// at the same time on a SafeBinaryMutex.
template <int Tag>
class MutexLock<SafeBinaryMutex<Tag>> {
friend class ConditionVariable;
- THREADING_NAMESPACE::unique_lock<THREADING_NAMESPACE::mutex> lock;
+ const SafeBinaryMutex<Tag> &mutex;
public:
- _ALWAYS_INLINE_ explicit MutexLock(const SafeBinaryMutex<Tag> &p_mutex) :
- lock(p_mutex.mutex) {
- SafeBinaryMutex<Tag>::count++;
- };
- _ALWAYS_INLINE_ ~MutexLock() {
- SafeBinaryMutex<Tag>::count--;
- };
+ explicit MutexLock(const SafeBinaryMutex<Tag> &p_mutex) :
+ mutex(p_mutex) {
+ mutex.lock();
+ }
+
+ ~MutexLock() {
+ mutex.unlock();
+ }
+
+ _ALWAYS_INLINE_ void temp_relock() const {
+ mutex.lock();
+ }
+
+ _ALWAYS_INLINE_ void temp_unlock() const {
+ mutex.unlock();
+ }
+
+ // TODO: Implement a `try_temp_relock` if needed (will also need a dummy method below).
};
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
#else // No threads.
template <int Tag>
-class SafeBinaryMutex : public MutexImpl {
- static thread_local uint32_t count;
+class SafeBinaryMutex {
+ struct TLSData {
+ TLSData(SafeBinaryMutex<Tag> &p_mutex) {}
+ };
+ static thread_local TLSData tls_data;
+
+public:
+ void lock() const {}
+ void unlock() const {}
};
template <int Tag>
@@ -117,6 +143,9 @@ class MutexLock<SafeBinaryMutex<Tag>> {
public:
MutexLock(const SafeBinaryMutex<Tag> &p_mutex) {}
~MutexLock() {}
+
+ void temp_relock() const {}
+ void temp_unlock() const {}
};
#endif // THREADS_ENABLED