| 
									
										
										
										
											2023-01-05 13:25:55 +01:00
										 |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*  ref_counted.cpp                                                       */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*                         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.                 */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							| 
									
										
										
										
											2018-01-05 00:50:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 18:03:15 +02:00
										 |  |  | #include "ref_counted.h"
 | 
					
						
							| 
									
										
										
										
											2017-01-16 08:04:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-07 19:33:38 -03:00
										 |  |  | #include "core/object/script_language.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 18:03:15 +02:00
										 |  |  | bool RefCounted::init_ref() { | 
					
						
							| 
									
										
										
										
											2017-08-19 19:41:11 +07:00
										 |  |  | 	if (reference()) { | 
					
						
							| 
									
										
										
										
											2019-09-04 00:04:37 +08:00
										 |  |  | 		if (!is_referenced() && refcount_init.unref()) { | 
					
						
							| 
									
										
										
										
											2017-08-19 19:41:11 +07:00
										 |  |  | 			unreference(); // first referencing is already 1, so compensate for the ref above
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 18:03:15 +02:00
										 |  |  | void RefCounted::_bind_methods() { | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("init_ref"), &RefCounted::init_ref); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("reference"), &RefCounted::reference); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("unreference"), &RefCounted::unreference); | 
					
						
							| 
									
										
										
										
											2022-09-19 15:45:45 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_reference_count"), &RefCounted::get_reference_count); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-19 15:45:45 +01:00
										 |  |  | int RefCounted::get_reference_count() const { | 
					
						
							| 
									
										
										
										
											2015-04-18 19:06:58 -03:00
										 |  |  | 	return refcount.get(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 18:03:15 +02:00
										 |  |  | bool RefCounted::reference() { | 
					
						
							| 
									
										
										
										
											2019-09-04 00:04:37 +08:00
										 |  |  | 	uint32_t rc_val = refcount.refval(); | 
					
						
							|  |  |  | 	bool success = rc_val != 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (success && rc_val <= 2 /* higher is not relevant */) { | 
					
						
							| 
									
										
										
										
											2018-02-22 15:34:08 +01:00
										 |  |  | 		if (get_script_instance()) { | 
					
						
							|  |  |  | 			get_script_instance()->refcount_incremented(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-06-04 14:33:48 -03:00
										 |  |  | 		if (_get_extension() && _get_extension()->reference) { | 
					
						
							|  |  |  | 			_get_extension()->reference(_get_extension_instance()); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-07-08 16:16:02 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		_instance_binding_reference(true); | 
					
						
							| 
									
										
										
										
											2016-06-21 19:34:45 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-19 19:41:11 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return success; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-08-19 19:41:11 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 18:03:15 +02:00
										 |  |  | bool RefCounted::unreference() { | 
					
						
							| 
									
										
										
										
											2019-09-04 00:04:37 +08:00
										 |  |  | 	uint32_t rc_val = refcount.unrefval(); | 
					
						
							|  |  |  | 	bool die = rc_val == 0; | 
					
						
							| 
									
										
										
										
											2016-06-21 19:34:45 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-04 00:04:37 +08:00
										 |  |  | 	if (rc_val <= 1 /* higher is not relevant */) { | 
					
						
							| 
									
										
										
										
											2018-02-22 15:34:08 +01:00
										 |  |  | 		if (get_script_instance()) { | 
					
						
							|  |  |  | 			bool script_ret = get_script_instance()->refcount_decremented(); | 
					
						
							|  |  |  | 			die = die && script_ret; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-06-04 14:33:48 -03:00
										 |  |  | 		if (_get_extension() && _get_extension()->unreference) { | 
					
						
							|  |  |  | 			_get_extension()->unreference(_get_extension_instance()); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-07-08 16:16:02 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-12 08:38:33 +02:00
										 |  |  | 		bool binding_ret = _instance_binding_reference(false); | 
					
						
							|  |  |  | 		die = die && binding_ret; | 
					
						
							| 
									
										
										
										
											2016-06-21 19:34:45 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return die; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 18:03:15 +02:00
										 |  |  | RefCounted::RefCounted() : | 
					
						
							| 
									
										
										
										
											2020-02-13 16:03:10 -03:00
										 |  |  | 		Object(true) { | 
					
						
							| 
									
										
										
										
											2025-06-22 23:08:23 +01:00
										 |  |  | 	_define_ancestry(AncestralClass::REF_COUNTED); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	refcount.init(); | 
					
						
							|  |  |  | 	refcount_init.init(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Variant WeakRef::get_ref() const { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (ref.is_null()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return Variant(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Object *obj = ObjectDB::get_instance(ref); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!obj) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return Variant(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-06-04 18:03:15 +02:00
										 |  |  | 	RefCounted *r = cast_to<RefCounted>(obj); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	if (r) { | 
					
						
							| 
									
										
										
										
											2022-05-03 01:43:50 +02:00
										 |  |  | 		return Ref<RefCounted>(r); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WeakRef::set_obj(Object *p_object) { | 
					
						
							| 
									
										
										
										
											2020-02-12 14:24:06 -03:00
										 |  |  | 	ref = p_object ? p_object->get_instance_id() : ObjectID(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-03 01:43:50 +02:00
										 |  |  | void WeakRef::set_ref(const Ref<RefCounted> &p_ref) { | 
					
						
							| 
									
										
										
										
											2020-02-12 14:24:06 -03:00
										 |  |  | 	ref = p_ref.is_valid() ? p_ref->get_instance_id() : ObjectID(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WeakRef::_bind_methods() { | 
					
						
							| 
									
										
										
										
											2017-08-09 13:19:41 +02:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_ref"), &WeakRef::get_ref); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } |