mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 21:51:22 +00:00 
			
		
		
		
	Extract 'SafeBinaryMutex' to separate header
This change simply extracts 'SafeBinaryMutex' from 'mutex.h' to
    'safe_binary_mutex.h', in an effort to reduce the compilation
    speed impact of including `mutex.h`.
			
			
This commit is contained in:
		
							parent
							
								
									b4e2a24c1f
								
							
						
					
					
						commit
						71e0082ab0
					
				
					 4 changed files with 128 additions and 80 deletions
				
			
		|  | @ -36,6 +36,7 @@ | ||||||
| #include "core/object/script_language.h" | #include "core/object/script_language.h" | ||||||
| #include "core/os/condition_variable.h" | #include "core/os/condition_variable.h" | ||||||
| #include "core/os/os.h" | #include "core/os/os.h" | ||||||
|  | #include "core/os/safe_binary_mutex.h" | ||||||
| #include "core/string/print_string.h" | #include "core/string/print_string.h" | ||||||
| #include "core/string/translation.h" | #include "core/string/translation.h" | ||||||
| #include "core/variant/variant_parser.h" | #include "core/variant/variant_parser.h" | ||||||
|  |  | ||||||
|  | @ -39,6 +39,9 @@ | ||||||
| 
 | 
 | ||||||
| class ConditionVariable; | class ConditionVariable; | ||||||
| 
 | 
 | ||||||
|  | template <int Tag> | ||||||
|  | class SafeBinaryMutex; | ||||||
|  | 
 | ||||||
| class ResourceFormatLoader : public RefCounted { | class ResourceFormatLoader : public RefCounted { | ||||||
| 	GDCLASS(ResourceFormatLoader, RefCounted); | 	GDCLASS(ResourceFormatLoader, RefCounted); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -70,56 +70,6 @@ public: | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // 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).
 |  | ||||||
| // - Must have recursive semnantics (or simulate, as this one does).
 |  | ||||||
| // The implementation keeps the lock count in TS. Therefore, only
 |  | ||||||
| // one object of each version of the template can exists; hence the Tag argument.
 |  | ||||||
| // Tags must be unique across the Godot codebase.
 |  | ||||||
| // Also, don't forget to declare the thread_local variable on each use.
 |  | ||||||
| template <int Tag> |  | ||||||
| class SafeBinaryMutex { |  | ||||||
| 	friend class MutexLock<SafeBinaryMutex>; |  | ||||||
| 
 |  | ||||||
| 	using StdMutexType = THREADING_NAMESPACE::mutex; |  | ||||||
| 
 |  | ||||||
| 	mutable THREADING_NAMESPACE::mutex mutex; |  | ||||||
| 	static thread_local uint32_t count; |  | ||||||
| 
 |  | ||||||
| public: |  | ||||||
| 	_ALWAYS_INLINE_ void lock() const { |  | ||||||
| 		if (++count == 1) { |  | ||||||
| 			mutex.lock(); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	_ALWAYS_INLINE_ void unlock() const { |  | ||||||
| 		DEV_ASSERT(count); |  | ||||||
| 		if (--count == 0) { |  | ||||||
| 			mutex.unlock(); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	_ALWAYS_INLINE_ bool try_lock() const { |  | ||||||
| 		if (count) { |  | ||||||
| 			count++; |  | ||||||
| 			return true; |  | ||||||
| 		} else { |  | ||||||
| 			if (mutex.try_lock()) { |  | ||||||
| 				count++; |  | ||||||
| 				return true; |  | ||||||
| 			} else { |  | ||||||
| 				return false; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	~SafeBinaryMutex() { |  | ||||||
| 		DEV_ASSERT(!count); |  | ||||||
| 	} |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| template <class MutexT> | template <class MutexT> | ||||||
| class MutexLock { | class MutexLock { | ||||||
| 	friend class ConditionVariable; | 	friend class ConditionVariable; | ||||||
|  | @ -131,24 +81,6 @@ public: | ||||||
| 			lock(p_mutex.mutex) {} | 			lock(p_mutex.mutex) {} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // 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; |  | ||||||
| 
 |  | ||||||
| public: |  | ||||||
| 	_ALWAYS_INLINE_ explicit MutexLock(const SafeBinaryMutex<Tag> &p_mutex) : |  | ||||||
| 			lock(p_mutex.mutex) { |  | ||||||
| 		SafeBinaryMutex<Tag>::count++; |  | ||||||
| 	}; |  | ||||||
| 	_ALWAYS_INLINE_ ~MutexLock() { |  | ||||||
| 		SafeBinaryMutex<Tag>::count--; |  | ||||||
| 	}; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| using Mutex = MutexImpl<THREADING_NAMESPACE::recursive_mutex>; // Recursive, for general use
 | using Mutex = MutexImpl<THREADING_NAMESPACE::recursive_mutex>; // Recursive, for general use
 | ||||||
| using BinaryMutex = MutexImpl<THREADING_NAMESPACE::mutex>; // Non-recursive, handle with care
 | using BinaryMutex = MutexImpl<THREADING_NAMESPACE::mutex>; // Non-recursive, handle with care
 | ||||||
| 
 | 
 | ||||||
|  | @ -168,24 +100,12 @@ public: | ||||||
| 	bool try_lock() const { return true; } | 	bool try_lock() const { return true; } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template <int Tag> |  | ||||||
| class SafeBinaryMutex : public MutexImpl { |  | ||||||
| 	static thread_local uint32_t count; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| template <class MutexT> | template <class MutexT> | ||||||
| class MutexLock { | class MutexLock { | ||||||
| public: | public: | ||||||
| 	MutexLock(const MutexT &p_mutex) {} | 	MutexLock(const MutexT &p_mutex) {} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template <int Tag> |  | ||||||
| class MutexLock<SafeBinaryMutex<Tag>> { |  | ||||||
| public: |  | ||||||
| 	MutexLock(const SafeBinaryMutex<Tag> &p_mutex) {} |  | ||||||
| 	~MutexLock() {} |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| using Mutex = MutexImpl; | using Mutex = MutexImpl; | ||||||
| using BinaryMutex = MutexImpl; | using BinaryMutex = MutexImpl; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										124
									
								
								core/os/safe_binary_mutex.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								core/os/safe_binary_mutex.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,124 @@ | ||||||
|  | /**************************************************************************/ | ||||||
|  | /*  safe_binary_mutex.h                                                   */ | ||||||
|  | /**************************************************************************/ | ||||||
|  | /*                         This file is part of:                          */ | ||||||
|  | /*                             GODOT ENGINE                               */ | ||||||
|  | /*                        https://godotengine.org                         */ | ||||||
|  | /**************************************************************************/ | ||||||
|  | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ | ||||||
|  | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */ | ||||||
|  | /*                                                                        */ | ||||||
|  | /* Permission is hereby granted, free of charge, to any person obtaining  */ | ||||||
|  | /* a copy of this software and associated documentation files (the        */ | ||||||
|  | /* "Software"), to deal in the Software without restriction, including    */ | ||||||
|  | /* without limitation the rights to use, copy, modify, merge, publish,    */ | ||||||
|  | /* distribute, sublicense, and/or sell copies of the Software, and to     */ | ||||||
|  | /* permit persons to whom the Software is furnished to do so, subject to  */ | ||||||
|  | /* the following conditions:                                              */ | ||||||
|  | /*                                                                        */ | ||||||
|  | /* The above copyright notice and this permission notice shall be         */ | ||||||
|  | /* included in all copies or substantial portions of the Software.        */ | ||||||
|  | /*                                                                        */ | ||||||
|  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */ | ||||||
|  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */ | ||||||
|  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ | ||||||
|  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */ | ||||||
|  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */ | ||||||
|  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */ | ||||||
|  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */ | ||||||
|  | /**************************************************************************/ | ||||||
|  | 
 | ||||||
|  | #ifndef SAFE_BINARY_MUTEX_H | ||||||
|  | #define SAFE_BINARY_MUTEX_H | ||||||
|  | 
 | ||||||
|  | #include "core/error/error_macros.h" | ||||||
|  | #include "core/os/mutex.h" | ||||||
|  | #include "core/typedefs.h" | ||||||
|  | 
 | ||||||
|  | #ifdef THREADS_ENABLED | ||||||
|  | 
 | ||||||
|  | // 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).
 | ||||||
|  | // - Must have recursive semnantics (or simulate, as this one does).
 | ||||||
|  | // The implementation keeps the lock count in TS. Therefore, only
 | ||||||
|  | // one object of each version of the template can exists; hence the Tag argument.
 | ||||||
|  | // Tags must be unique across the Godot codebase.
 | ||||||
|  | // Also, don't forget to declare the thread_local variable on each use.
 | ||||||
|  | template <int Tag> | ||||||
|  | class SafeBinaryMutex { | ||||||
|  | 	friend class MutexLock<SafeBinaryMutex>; | ||||||
|  | 
 | ||||||
|  | 	using StdMutexType = THREADING_NAMESPACE::mutex; | ||||||
|  | 
 | ||||||
|  | 	mutable THREADING_NAMESPACE::mutex mutex; | ||||||
|  | 	static thread_local uint32_t count; | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  | 	_ALWAYS_INLINE_ void lock() const { | ||||||
|  | 		if (++count == 1) { | ||||||
|  | 			mutex.lock(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	_ALWAYS_INLINE_ void unlock() const { | ||||||
|  | 		DEV_ASSERT(count); | ||||||
|  | 		if (--count == 0) { | ||||||
|  | 			mutex.unlock(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	_ALWAYS_INLINE_ bool try_lock() const { | ||||||
|  | 		if (count) { | ||||||
|  | 			count++; | ||||||
|  | 			return true; | ||||||
|  | 		} else { | ||||||
|  | 			if (mutex.try_lock()) { | ||||||
|  | 				count++; | ||||||
|  | 				return true; | ||||||
|  | 			} else { | ||||||
|  | 				return false; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	~SafeBinaryMutex() { | ||||||
|  | 		DEV_ASSERT(!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; | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  | 	_ALWAYS_INLINE_ explicit MutexLock(const SafeBinaryMutex<Tag> &p_mutex) : | ||||||
|  | 			lock(p_mutex.mutex) { | ||||||
|  | 		SafeBinaryMutex<Tag>::count++; | ||||||
|  | 	}; | ||||||
|  | 	_ALWAYS_INLINE_ ~MutexLock() { | ||||||
|  | 		SafeBinaryMutex<Tag>::count--; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #else // No threads.
 | ||||||
|  | 
 | ||||||
|  | template <int Tag> | ||||||
|  | class SafeBinaryMutex : public MutexImpl { | ||||||
|  | 	static thread_local uint32_t count; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | template <int Tag> | ||||||
|  | class MutexLock<SafeBinaryMutex<Tag>> { | ||||||
|  | public: | ||||||
|  | 	MutexLock(const SafeBinaryMutex<Tag> &p_mutex) {} | ||||||
|  | 	~MutexLock() {} | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif // THREADS_ENABLED
 | ||||||
|  | 
 | ||||||
|  | #endif // SAFE_BINARY_MUTEX_H
 | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 vittorioromeo
						vittorioromeo