| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  safe_refcount.h                                                      */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							| 
									
										
										
										
											2017-08-27 14:16:55 +02:00
										 |  |  | /*                      https://godotengine.org                          */ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2022-01-13 09:45:09 +01:00
										 |  |  | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							|  |  |  | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* 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.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2018-01-05 00:50:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | #ifndef SAFE_REFCOUNT_H
 | 
					
						
							|  |  |  | #define SAFE_REFCOUNT_H
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-11 18:13:45 +02:00
										 |  |  | #include "core/typedefs.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | #if !defined(NO_THREADS)
 | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | #include <atomic>
 | 
					
						
							| 
									
										
										
										
											2021-04-22 16:23:13 +02:00
										 |  |  | #include <type_traits>
 | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | // Design goals for these classes:
 | 
					
						
							|  |  |  | // - No automatic conversions or arithmetic operators,
 | 
					
						
							|  |  |  | //   to keep explicit the use of atomics everywhere.
 | 
					
						
							|  |  |  | // - Using acquire-release semantics, even to set the first value.
 | 
					
						
							|  |  |  | //   The first value may be set relaxedly in many cases, but adding the distinction
 | 
					
						
							|  |  |  | //   between relaxed and unrelaxed operation to the interface would make it needlessly
 | 
					
						
							|  |  |  | //   flexible. There's negligible waste in having release semantics for the initial
 | 
					
						
							|  |  |  | //   value and, as an important benefit, you can be sure the value is properly synchronized
 | 
					
						
							|  |  |  | //   even with threads that are already running.
 | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-18 23:31:34 +01:00
										 |  |  | // This is used in very specific areas of the engine where it's critical that these guarantees are held
 | 
					
						
							|  |  |  | #define SAFE_NUMERIC_TYPE_PUN_GUARANTEES(m_type)                        \
 | 
					
						
							|  |  |  | 	static_assert(sizeof(SafeNumeric<m_type>) == sizeof(m_type), "");   \ | 
					
						
							|  |  |  | 	static_assert(alignof(SafeNumeric<m_type>) == alignof(m_type), ""); \ | 
					
						
							| 
									
										
										
										
											2021-05-04 14:20:36 +02:00
										 |  |  | 	static_assert(std::is_trivially_destructible<std::atomic<m_type>>::value, ""); | 
					
						
							| 
									
										
										
										
											2021-02-18 23:31:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined(DEBUG_ENABLED)
 | 
					
						
							|  |  |  | void check_lockless_atomics(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | template <class T> | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | class SafeNumeric { | 
					
						
							|  |  |  | 	std::atomic<T> value; | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | public: | 
					
						
							|  |  |  | 	_ALWAYS_INLINE_ void set(T p_value) { | 
					
						
							|  |  |  | 		value.store(p_value, std::memory_order_release); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ T get() const { | 
					
						
							|  |  |  | 		return value.load(std::memory_order_acquire); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ T increment() { | 
					
						
							|  |  |  | 		return value.fetch_add(1, std::memory_order_acq_rel) + 1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	// Returns the original value instead of the new one
 | 
					
						
							|  |  |  | 	_ALWAYS_INLINE_ T postincrement() { | 
					
						
							|  |  |  | 		return value.fetch_add(1, std::memory_order_acq_rel); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ T decrement() { | 
					
						
							|  |  |  | 		return value.fetch_sub(1, std::memory_order_acq_rel) - 1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	// Returns the original value instead of the new one
 | 
					
						
							|  |  |  | 	_ALWAYS_INLINE_ T postdecrement() { | 
					
						
							|  |  |  | 		return value.fetch_sub(1, std::memory_order_acq_rel); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ T add(T p_value) { | 
					
						
							|  |  |  | 		return value.fetch_add(p_value, std::memory_order_acq_rel) + p_value; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	// Returns the original value instead of the new one
 | 
					
						
							|  |  |  | 	_ALWAYS_INLINE_ T postadd(T p_value) { | 
					
						
							|  |  |  | 		return value.fetch_add(p_value, std::memory_order_acq_rel); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_ALWAYS_INLINE_ T sub(T p_value) { | 
					
						
							|  |  |  | 		return value.fetch_sub(p_value, std::memory_order_acq_rel) - p_value; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Returns the original value instead of the new one
 | 
					
						
							|  |  |  | 	_ALWAYS_INLINE_ T postsub(T p_value) { | 
					
						
							|  |  |  | 		return value.fetch_sub(p_value, std::memory_order_acq_rel); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ T exchange_if_greater(T p_value) { | 
					
						
							|  |  |  | 		while (true) { | 
					
						
							|  |  |  | 			T tmp = value.load(std::memory_order_acquire); | 
					
						
							|  |  |  | 			if (tmp >= p_value) { | 
					
						
							|  |  |  | 				return tmp; // already greater, or equal
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (value.compare_exchange_weak(tmp, p_value, std::memory_order_release)) { | 
					
						
							|  |  |  | 				return p_value; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ T conditional_increment() { | 
					
						
							|  |  |  | 		while (true) { | 
					
						
							|  |  |  | 			T c = value.load(std::memory_order_acquire); | 
					
						
							|  |  |  | 			if (c == 0) { | 
					
						
							|  |  |  | 				return 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (value.compare_exchange_weak(c, c + 1, std::memory_order_release)) { | 
					
						
							|  |  |  | 				return c + 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ explicit SafeNumeric<T>(T p_value = static_cast<T>(0)) { | 
					
						
							|  |  |  | 		set(p_value); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | class SafeFlag { | 
					
						
							|  |  |  | 	std::atomic_bool flag; | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | public: | 
					
						
							|  |  |  | 	_ALWAYS_INLINE_ bool is_set() const { | 
					
						
							|  |  |  | 		return flag.load(std::memory_order_acquire); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ void set() { | 
					
						
							|  |  |  | 		flag.store(true, std::memory_order_release); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ void clear() { | 
					
						
							|  |  |  | 		flag.store(false, std::memory_order_release); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ void set_to(bool p_value) { | 
					
						
							|  |  |  | 		flag.store(p_value, std::memory_order_release); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ explicit SafeFlag(bool p_value = false) { | 
					
						
							|  |  |  | 		set_to(p_value); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | class SafeRefCount { | 
					
						
							|  |  |  | 	SafeNumeric<uint32_t> count; | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | public: | 
					
						
							|  |  |  | 	_ALWAYS_INLINE_ bool ref() { // true on success
 | 
					
						
							|  |  |  | 		return count.conditional_increment() != 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ uint32_t refval() { // none-zero on success
 | 
					
						
							|  |  |  | 		return count.conditional_increment(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ bool unref() { // true if must be disposed of
 | 
					
						
							|  |  |  | 		return count.decrement() == 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ uint32_t unrefval() { // 0 if must be disposed of
 | 
					
						
							|  |  |  | 		return count.decrement(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ uint32_t get() const { | 
					
						
							|  |  |  | 		return count.get(); | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ void init(uint32_t p_value = 1) { | 
					
						
							|  |  |  | 		count.set(p_value); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | template <class T> | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | class SafeNumeric { | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  | 	T value; | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | public: | 
					
						
							|  |  |  | 	_ALWAYS_INLINE_ void set(T p_value) { | 
					
						
							|  |  |  | 		value = p_value; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ T get() const { | 
					
						
							|  |  |  | 		return value; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ T increment() { | 
					
						
							|  |  |  | 		return ++value; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ T postincrement() { | 
					
						
							|  |  |  | 		return value++; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ T decrement() { | 
					
						
							|  |  |  | 		return --value; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ T postdecrement() { | 
					
						
							|  |  |  | 		return value--; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ T add(T p_value) { | 
					
						
							|  |  |  | 		return value += p_value; | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ T postadd(T p_value) { | 
					
						
							|  |  |  | 		T old = value; | 
					
						
							|  |  |  | 		value += p_value; | 
					
						
							|  |  |  | 		return old; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-24 12:11:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ T sub(T p_value) { | 
					
						
							|  |  |  | 		return value -= p_value; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ T postsub(T p_value) { | 
					
						
							|  |  |  | 		T old = value; | 
					
						
							|  |  |  | 		value -= p_value; | 
					
						
							|  |  |  | 		return old; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-06-22 05:05:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ T exchange_if_greater(T p_value) { | 
					
						
							|  |  |  | 		if (value < p_value) { | 
					
						
							|  |  |  | 			value = p_value; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return value; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ T conditional_increment() { | 
					
						
							| 
									
										
										
										
											2021-02-25 21:22:01 +01:00
										 |  |  | 		if (value == 0) { | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 			return 0; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			return ++value; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ explicit SafeNumeric<T>(T p_value = static_cast<T>(0)) : | 
					
						
							|  |  |  | 			value(p_value) { | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | class SafeFlag { | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  | 	bool flag; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | public: | 
					
						
							|  |  |  | 	_ALWAYS_INLINE_ bool is_set() const { | 
					
						
							|  |  |  | 		return flag; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ void set() { | 
					
						
							|  |  |  | 		flag = true; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ void clear() { | 
					
						
							|  |  |  | 		flag = false; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ void set_to(bool p_value) { | 
					
						
							|  |  |  | 		flag = p_value; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ explicit SafeFlag(bool p_value = false) : | 
					
						
							|  |  |  | 			flag(p_value) {} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class SafeRefCount { | 
					
						
							|  |  |  | 	uint32_t count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  | 	_ALWAYS_INLINE_ bool ref() { // true on success
 | 
					
						
							|  |  |  | 		if (count != 0) { | 
					
						
							|  |  |  | 			++count; | 
					
						
							|  |  |  | 			return true; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ uint32_t refval() { // none-zero on success
 | 
					
						
							|  |  |  | 		if (count != 0) { | 
					
						
							|  |  |  | 			return ++count; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-09-04 00:04:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ bool unref() { // true if must be disposed of
 | 
					
						
							|  |  |  | 		return --count == 0; | 
					
						
							| 
									
										
										
										
											2019-09-04 00:04:37 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ uint32_t unrefval() { // 0 if must be disposed of
 | 
					
						
							|  |  |  | 		return --count; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 	_ALWAYS_INLINE_ uint32_t get() const { | 
					
						
							| 
									
										
										
										
											2017-01-06 10:15:44 -03:00
										 |  |  | 		return count; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-25 00:01:55 +02:00
										 |  |  | 	_ALWAYS_INLINE_ void init(uint32_t p_value = 1) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		count = p_value; | 
					
						
							| 
									
										
										
										
											2017-01-06 10:15:44 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	SafeRefCount() : | 
					
						
							|  |  |  | 			count(0) {} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2021-01-31 13:34:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #endif // SAFE_REFCOUNT_H
 |