|
1 | 1 | /**************************************************************************/ |
2 | | -/* mutex_lock.hpp */ |
| 2 | +/* mutex.hpp */ |
3 | 3 | /**************************************************************************/ |
4 | 4 | /* This file is part of: */ |
5 | 5 | /* GODOT ENGINE */ |
|
30 | 30 |
|
31 | 31 | #pragma once |
32 | 32 |
|
33 | | -#include <godot_cpp/classes/mutex.hpp> |
| 33 | +#include <godot_cpp/core/defs.hpp> |
| 34 | + |
| 35 | +#ifdef MINGW_ENABLED |
| 36 | +#define MINGW_STDTHREAD_REDUNDANCY_WARNING |
| 37 | +#include <thirdparty/mingw-std-threads/mingw.mutex.h> |
| 38 | +#define THREADING_NAMESPACE mingw_stdthread |
| 39 | +#else |
| 40 | +#include <mutex> |
| 41 | +#define THREADING_NAMESPACE std |
| 42 | +#endif |
34 | 43 |
|
35 | 44 | namespace godot { |
36 | 45 |
|
37 | | -class MutexLock { |
38 | | - const Mutex &mutex; |
| 46 | +#ifdef THREADS_ENABLED |
| 47 | + |
| 48 | +template <typename MutexT> |
| 49 | +class MutexLock; |
| 50 | + |
| 51 | +template <typename StdMutexT> |
| 52 | +class MutexImpl { |
| 53 | + friend class MutexLock<MutexImpl<StdMutexT>>; |
| 54 | + |
| 55 | + using StdMutexType = StdMutexT; |
| 56 | + |
| 57 | + mutable StdMutexT mutex; |
39 | 58 |
|
40 | 59 | public: |
41 | | - _ALWAYS_INLINE_ explicit MutexLock(const Mutex &p_mutex) : |
42 | | - mutex(p_mutex) { |
43 | | - const_cast<Mutex *>(&mutex)->lock(); |
| 60 | + _ALWAYS_INLINE_ void lock() const { |
| 61 | + mutex.lock(); |
| 62 | + } |
| 63 | + |
| 64 | + _ALWAYS_INLINE_ void unlock() const { |
| 65 | + mutex.unlock(); |
44 | 66 | } |
45 | 67 |
|
46 | | - _ALWAYS_INLINE_ ~MutexLock() { |
47 | | - const_cast<Mutex *>(&mutex)->unlock(); |
| 68 | + _ALWAYS_INLINE_ bool try_lock() const { |
| 69 | + return mutex.try_lock(); |
48 | 70 | } |
49 | 71 | }; |
50 | 72 |
|
| 73 | +template <typename MutexT> |
| 74 | +class [[nodiscard]] MutexLock { |
| 75 | + mutable THREADING_NAMESPACE::unique_lock<typename MutexT::StdMutexType> lock; |
| 76 | + |
| 77 | +public: |
| 78 | + explicit MutexLock(const MutexT &p_mutex) : |
| 79 | + lock(p_mutex.mutex) {} |
| 80 | + |
| 81 | + // Clarification: all the funny syntax is needed so this function exists only for binary mutexes. |
| 82 | + template <typename T = MutexT> |
| 83 | + _ALWAYS_INLINE_ THREADING_NAMESPACE::unique_lock<THREADING_NAMESPACE::mutex> &_get_lock( |
| 84 | + typename std::enable_if<std::is_same<T, THREADING_NAMESPACE::mutex>::value> * = nullptr) const { |
| 85 | + return lock; |
| 86 | + } |
| 87 | + |
| 88 | + _ALWAYS_INLINE_ void temp_relock() const { |
| 89 | + lock.lock(); |
| 90 | + } |
| 91 | + |
| 92 | + _ALWAYS_INLINE_ void temp_unlock() const { |
| 93 | + lock.unlock(); |
| 94 | + } |
| 95 | + |
| 96 | + // TODO: Implement a `try_temp_relock` if needed (will also need a dummy method below). |
| 97 | +}; |
| 98 | + |
| 99 | +using Mutex = MutexImpl<THREADING_NAMESPACE::recursive_mutex>; // Recursive, for general use |
| 100 | +using BinaryMutex = MutexImpl<THREADING_NAMESPACE::mutex>; // Non-recursive, handle with care |
| 101 | + |
51 | 102 | #define _THREAD_SAFE_CLASS_ mutable Mutex _thread_safe_; |
52 | 103 | #define _THREAD_SAFE_METHOD_ MutexLock _thread_safe_method_(_thread_safe_); |
53 | 104 | #define _THREAD_SAFE_LOCK_ _thread_safe_.lock(); |
54 | 105 | #define _THREAD_SAFE_UNLOCK_ _thread_safe_.unlock(); |
55 | 106 |
|
| 107 | +#else // No threads. |
| 108 | + |
| 109 | +class MutexImpl { |
| 110 | + mutable THREADING_NAMESPACE::mutex mutex; |
| 111 | + |
| 112 | +public: |
| 113 | + void lock() const {} |
| 114 | + void unlock() const {} |
| 115 | + bool try_lock() const { return true; } |
| 116 | +}; |
| 117 | + |
| 118 | +template <typename MutexT> |
| 119 | +class [[nodiscard]] MutexLock { |
| 120 | +public: |
| 121 | + MutexLock(const MutexT &p_mutex) {} |
| 122 | + |
| 123 | + void temp_relock() const {} |
| 124 | + void temp_unlock() const {} |
| 125 | +}; |
| 126 | + |
| 127 | +using Mutex = MutexImpl; |
| 128 | +using BinaryMutex = MutexImpl; |
| 129 | + |
| 130 | +#define _THREAD_SAFE_CLASS_ |
| 131 | +#define _THREAD_SAFE_METHOD_ |
| 132 | +#define _THREAD_SAFE_LOCK_ |
| 133 | +#define _THREAD_SAFE_UNLOCK_ |
| 134 | + |
| 135 | +#endif // THREADS_ENABLED |
| 136 | + |
56 | 137 | } // namespace godot |
0 commit comments