mirror of
https://github.com/godotengine/godot.git
synced 2024-11-22 12:12:28 +00:00
Add NOTIFICATION_PREDELETE_CLEANUP
notification
New notification sent after `NOTIFICATION_PREDELETE` to let Objects cleanup at the very end, it should be the last notification sent.
This commit is contained in:
parent
f8818f85e6
commit
9750e49c57
@ -198,6 +198,7 @@ bool Object::_predelete() {
|
||||
notification(NOTIFICATION_PREDELETE, true);
|
||||
if (_predelete_ok) {
|
||||
_class_name_ptr = nullptr; // Must restore, so constructors/destructors have proper class name access at each stage.
|
||||
notification(NOTIFICATION_PREDELETE_CLEANUP, true);
|
||||
}
|
||||
return _predelete_ok;
|
||||
}
|
||||
|
@ -801,6 +801,8 @@ public:
|
||||
NOTIFICATION_POSTINITIALIZE = 0,
|
||||
NOTIFICATION_PREDELETE = 1,
|
||||
NOTIFICATION_EXTENSION_RELOADED = 2,
|
||||
// Internal notification to send after NOTIFICATION_PREDELETE, not bound to scripting.
|
||||
NOTIFICATION_PREDELETE_CLEANUP = 3,
|
||||
};
|
||||
|
||||
/* TYPE API */
|
||||
|
@ -1985,24 +1985,31 @@ const Variant CSharpInstance::get_rpc_config() const {
|
||||
|
||||
void CSharpInstance::notification(int p_notification, bool p_reversed) {
|
||||
if (p_notification == Object::NOTIFICATION_PREDELETE) {
|
||||
// When NOTIFICATION_PREDELETE is sent, we also take the chance to call Dispose().
|
||||
// It's safe to call Dispose() multiple times and NOTIFICATION_PREDELETE is guaranteed
|
||||
if (base_ref_counted) {
|
||||
// At this point, Dispose() was already called (manually or from the finalizer).
|
||||
// The RefCounted wouldn't have reached 0 otherwise, since the managed side
|
||||
// references it and Dispose() needs to be called to release it.
|
||||
// However, this means C# RefCounted scripts can't receive NOTIFICATION_PREDELETE, but
|
||||
// this is likely the case with GDScript as well: https://github.com/godotengine/godot/issues/6784
|
||||
return;
|
||||
}
|
||||
} else if (p_notification == Object::NOTIFICATION_PREDELETE_CLEANUP) {
|
||||
// When NOTIFICATION_PREDELETE_CLEANUP is sent, we also take the chance to call Dispose().
|
||||
// It's safe to call Dispose() multiple times and NOTIFICATION_PREDELETE_CLEANUP is guaranteed
|
||||
// to be sent at least once, which happens right before the call to the destructor.
|
||||
|
||||
predelete_notified = true;
|
||||
|
||||
if (base_ref_counted) {
|
||||
// It's not safe to proceed if the owner derives RefCounted and the refcount reached 0.
|
||||
// At this point, Dispose() was already called (manually or from the finalizer) so
|
||||
// that's not a problem. The refcount wouldn't have reached 0 otherwise, since the
|
||||
// managed side references it and Dispose() needs to be called to release it.
|
||||
// However, this means C# RefCounted scripts can't receive NOTIFICATION_PREDELETE, but
|
||||
// this is likely the case with GDScript as well: https://github.com/godotengine/godot/issues/6784
|
||||
// At this point, Dispose() was already called (manually or from the finalizer).
|
||||
// The RefCounted wouldn't have reached 0 otherwise, since the managed side
|
||||
// references it and Dispose() needs to be called to release it.
|
||||
return;
|
||||
}
|
||||
|
||||
_call_notification(p_notification, p_reversed);
|
||||
|
||||
// NOTIFICATION_PREDELETE_CLEANUP is not sent to scripts.
|
||||
// After calling Dispose() the C# instance can no longer be used,
|
||||
// so it should be the last thing we do.
|
||||
GDMonoCache::managed_callbacks.CSharpInstanceBridge_CallDispose(
|
||||
gchandle.get_intptr(), /* okIfNull */ false);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user