Exemple #1
0
void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) {
#ifdef DEBUG_ENABLED
	CRASH_COND(p_ptr == NULL);
#endif

	if (p_ptr->get_script_instance()) {
		CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(p_ptr->get_script_instance());
		if (cs_instance) {
			if (!cs_instance->is_destructing_script_instance()) {
				cs_instance->mono_object_disposed(p_obj);
				p_ptr->set_script_instance(NULL);
			}
			return;
		}
	}

	void *data = p_ptr->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());

	if (data) {
		CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
		if (script_binding.inited) {
			Ref<MonoGCHandle> &gchandle = script_binding.gchandle;
			if (gchandle.is_valid()) {
				CSharpLanguage::release_script_gchandle(p_obj, gchandle);
			}
		}
	}
}
Exemple #2
0
MonoObject *unmanaged_get_managed(Object *unmanaged) {
	if (unmanaged) {
		if (unmanaged->get_script_instance()) {
			CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(unmanaged->get_script_instance());

			if (cs_instance) {
				return cs_instance->get_mono_object();
			}
		}

		// If the owner does not have a CSharpInstance...

		void *data = unmanaged->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());

		if (data) {
			CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->value();

			Ref<MonoGCHandle> &gchandle = script_binding.gchandle;
			ERR_FAIL_COND_V(gchandle.is_null(), NULL);

			MonoObject *target = gchandle->get_target();

			if (target)
				return target;

			CSharpLanguage::get_singleton()->release_script_gchandle(gchandle);

			// Create a new one

#ifdef DEBUG_ENABLED
			CRASH_COND(script_binding.type_name == StringName());
			CRASH_COND(script_binding.wrapper_class == NULL);
#endif

			MonoObject *mono_object = GDMonoUtils::create_managed_for_godot_object(script_binding.wrapper_class, script_binding.type_name, unmanaged);
			ERR_FAIL_NULL_V(mono_object, NULL);

			gchandle->set_handle(MonoGCHandle::new_strong_handle(mono_object), MonoGCHandle::STRONG_HANDLE);

			// Tie managed to unmanaged
			Reference *ref = Object::cast_to<Reference>(unmanaged);

			if (ref) {
				// Unsafe refcount increment. The managed instance also counts as a reference.
				// This way if the unmanaged world has no references to our owner
				// but the managed instance is alive, the refcount will be 1 instead of 0.
				// See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)

				ref->reference();
			}

			return mono_object;
		}
	}

	return NULL;
}
Exemple #3
0
void _GodotSharp::_dispose_object(Object *p_object) {

	if (p_object->get_script_instance()) {
		CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(p_object->get_script_instance());
		if (cs_instance) {
			cs_instance->mono_object_disposed();
			return;
		}
	}

	// Unsafe refcount decrement. The managed instance also counts as a reference.
	// See: CSharpLanguage::alloc_instance_binding_data(Object *p_object)
	if (Object::cast_to<Reference>(p_object)->unreference()) {
		memdelete(p_object);
	}
}
Exemple #4
0
void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolean p_is_finalizer) {
#ifdef DEBUG_ENABLED
	CRASH_COND(p_ptr == NULL);
	// This is only called with Reference derived classes
	CRASH_COND(!Object::cast_to<Reference>(p_ptr));
#endif

	Reference *ref = static_cast<Reference *>(p_ptr);

	if (ref->get_script_instance()) {
		CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(ref->get_script_instance());
		if (cs_instance) {
			if (!cs_instance->is_destructing_script_instance()) {
				bool delete_owner;
				bool remove_script_instance;

				cs_instance->mono_object_disposed_baseref(p_obj, p_is_finalizer, delete_owner, remove_script_instance);

				if (delete_owner) {
					memdelete(ref);
				} else if (remove_script_instance) {
					ref->set_script_instance(NULL);
				}
			}
			return;
		}
	}

	// Unsafe refcount decrement. The managed instance also counts as a reference.
	// See: CSharpLanguage::alloc_instance_binding_data(Object *p_object)
	if (ref->unreference()) {
		memdelete(ref);
	} else {
		void *data = ref->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());

		if (data) {
			CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
			if (script_binding.inited) {
				Ref<MonoGCHandle> &gchandle = script_binding.gchandle;
				if (gchandle.is_valid()) {
					CSharpLanguage::release_script_gchandle(p_obj, gchandle);
				}
			}
		}
	}
}
Exemple #5
0
MonoObject *unmanaged_get_managed(Object *unmanaged) {
	if (unmanaged) {
		if (unmanaged->get_script_instance()) {
			CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(unmanaged->get_script_instance());

			if (cs_instance) {
				return cs_instance->get_mono_object();
			}
		}

		// Only called if the owner does not have a CSharpInstance
		void *data = unmanaged->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());

		if (data) {
			return ((Map<Object *, Ref<MonoGCHandle> >::Element *)data)->value()->get_target();
		}
	}

	return NULL;
}
Exemple #6
0
void _GodotSharp::queue_dispose(MonoObject *p_mono_object, Object *p_object) {

	if (GDMonoUtils::is_main_thread() && !GDMono::get_singleton()->is_finalizing_scripts_domain()) {
		_dispose_object(p_object);
	} else {
#ifndef NO_THREADS
		queue_mutex->lock();
#endif

		// This is our last chance to invoke notification predelete (this is being called from the finalizer)
		// We must use the MonoObject* passed by the finalizer, because the weak GC handle target returns NULL at this point
		CSharpInstance *si = CAST_CSHARP_INSTANCE(p_object->get_script_instance());
		if (si) {
			si->call_notification_no_check(p_mono_object, Object::NOTIFICATION_PREDELETE);
		}

		ENQUEUE_FOR_DISPOSAL(obj_delete_queue, p_object);

#ifndef NO_THREADS
		queue_mutex->unlock();
#endif
	}
}