| 1995 | } |
| 1996 | |
| 1997 | CSharpInstance::~CSharpInstance() { |
| 1998 | destructing_script_instance = true; |
| 1999 | |
| 2000 | // Must make sure event signals are not left dangling |
| 2001 | disconnect_event_signals(); |
| 2002 | |
| 2003 | if (!gchandle.is_released()) { |
| 2004 | if (!predelete_notified && !ref_dying) { |
| 2005 | // This destructor is not called from the owners destructor. |
| 2006 | // This could be being called from the owner's set_script_instance method, |
| 2007 | // meaning this script is being replaced with another one. If this is the case, |
| 2008 | // we must call Dispose here, because Dispose calls owner->set_script_instance(nullptr) |
| 2009 | // and that would mess up with the new script instance if called later. |
| 2010 | |
| 2011 | GDMonoCache::managed_callbacks.CSharpInstanceBridge_CallDispose( |
| 2012 | gchandle.get_intptr(), /* okIfNull */ true); |
| 2013 | } |
| 2014 | |
| 2015 | gchandle.release(); // Make sure the gchandle is released |
| 2016 | } |
| 2017 | |
| 2018 | // If not being called from the owner's destructor, and we still hold a reference to the owner |
| 2019 | if (base_ref_counted && !ref_dying && owner && unsafe_referenced) { |
| 2020 | // The owner's script or script instance is being replaced (or removed) |
| 2021 | |
| 2022 | // Transfer ownership to an "instance binding" |
| 2023 | |
| 2024 | RefCounted *rc_owner = static_cast<RefCounted *>(owner); |
| 2025 | |
| 2026 | // We will unreference the owner before referencing it again, so we need to keep it alive |
| 2027 | Ref<RefCounted> scope_keep_owner_alive(rc_owner); |
| 2028 | (void)scope_keep_owner_alive; |
| 2029 | |
| 2030 | // Unreference the owner here, before the new "instance binding" references it. |
| 2031 | // Otherwise, the unsafe reference debug checks will incorrectly detect a bug. |
| 2032 | bool die = _unreference_owner_unsafe(); |
| 2033 | CRASH_COND(die); // `owner_keep_alive` holds a reference, so it can't die |
| 2034 | |
| 2035 | void *data = CSharpLanguage::get_instance_binding_with_setup(owner); |
| 2036 | CRASH_COND(data == nullptr); |
| 2037 | CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)data)->get(); |
| 2038 | CRASH_COND(!script_binding.inited); |
| 2039 | |
| 2040 | #ifdef DEBUG_ENABLED |
| 2041 | // The "instance binding" holds a reference so the refcount should be at least 2 before `scope_keep_owner_alive` goes out of scope |
| 2042 | CRASH_COND(rc_owner->get_reference_count() <= 1); |
| 2043 | #endif // DEBUG_ENABLED |
| 2044 | } |
| 2045 | |
| 2046 | if (script.is_valid() && owner) { |
| 2047 | MutexLock lock(CSharpLanguage::get_singleton()->script_instances_mutex); |
| 2048 | |
| 2049 | #ifdef DEBUG_ENABLED |
| 2050 | // CSharpInstance must not be created unless it's going to be added to the list for sure |
| 2051 | HashSet<Object *>::Iterator match = script->instances.find(owner); |
| 2052 | CRASH_COND(!match); |
| 2053 | script->instances.remove(match); |
| 2054 | #else |
nothing calls this directly
no test coverage detected