mirror of https://github.com/godotengine/godot
Fix variant rejecting dying RefCounted
This commit is contained in:
parent
d2ada64a03
commit
f40646901b
|
|
@ -1092,10 +1092,16 @@ void Variant::ObjData::ref(const ObjData &p_from) {
|
|||
|
||||
*this = p_from;
|
||||
if (id.is_ref_counted()) {
|
||||
RefCounted *reference = static_cast<RefCounted *>(obj);
|
||||
// Assuming reference is not null because id.is_ref_counted() was true.
|
||||
if (!reference->reference()) {
|
||||
*this = ObjData();
|
||||
RefCounted *reference = static_cast<RefCounted *>(obj);
|
||||
// The RefCounted object might be dying (count == 0) but there are
|
||||
// still reasons of using it (e.g. predeleted callback). In such case
|
||||
// we treat it as a regular object and do not attempt to ref-count it
|
||||
// (will not succeed and end up with a null object).
|
||||
if (reference->get_reference_count() > 0) {
|
||||
if (!reference->reference()) {
|
||||
*this = ObjData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1114,8 +1120,10 @@ void Variant::ObjData::ref_pointer(Object *p_object) {
|
|||
*this = ObjData{ p_object->get_instance_id(), p_object };
|
||||
if (p_object->is_ref_counted()) {
|
||||
RefCounted *reference = static_cast<RefCounted *>(p_object);
|
||||
if (!reference->init_ref()) {
|
||||
*this = ObjData();
|
||||
if (reference->get_reference_count() > 0) {
|
||||
if (!reference->init_ref()) {
|
||||
*this = ObjData();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1129,9 +1137,11 @@ void Variant::ObjData::unref() {
|
|||
// Mirrors Ref::unref in refcounted.h
|
||||
if (id.is_ref_counted()) {
|
||||
RefCounted *reference = static_cast<RefCounted *>(obj);
|
||||
// Assuming reference is not null because id.is_ref_counted() was true.
|
||||
if (reference->unreference()) {
|
||||
memdelete(reference);
|
||||
if (reference->get_reference_count() > 0) {
|
||||
// Assuming reference is not null because id.is_ref_counted() was true.
|
||||
if (reference->unreference()) {
|
||||
memdelete(reference);
|
||||
}
|
||||
}
|
||||
}
|
||||
*this = ObjData();
|
||||
|
|
|
|||
|
|
@ -31,8 +31,10 @@
|
|||
#ifndef TEST_VARIANT_H
|
||||
#define TEST_VARIANT_H
|
||||
|
||||
#include "core/object/ref_counted.h"
|
||||
#include "core/variant/variant.h"
|
||||
#include "core/variant/variant_parser.h"
|
||||
#include "core/variant/variant_utility.h"
|
||||
|
||||
#include "tests/test_macros.h"
|
||||
|
||||
|
|
@ -2216,6 +2218,24 @@ TEST_CASE("[Variant] Operator NOT") {
|
|||
}
|
||||
}
|
||||
|
||||
TEST_CASE("[Variant] Constructed from a dying RefCounted") {
|
||||
RefCounted *obj = memnew(RefCounted);
|
||||
const uint64_t obj_id = obj->get_instance_id();
|
||||
obj->init_ref();
|
||||
CHECK(obj->get_reference_count() == 1);
|
||||
obj->unreference();
|
||||
CHECK(obj->get_reference_count() == 0);
|
||||
{
|
||||
Variant v(obj);
|
||||
CHECK(!v.is_null());
|
||||
CHECK(VariantUtilityFunctions::is_instance_valid(v));
|
||||
Object *o = v;
|
||||
CHECK(o == (Object *)obj);
|
||||
}
|
||||
CHECK(VariantUtilityFunctions::is_instance_id_valid(obj_id));
|
||||
memdelete(obj);
|
||||
}
|
||||
|
||||
} // namespace TestVariant
|
||||
|
||||
#endif // TEST_VARIANT_H
|
||||
|
|
|
|||
Loading…
Reference in New Issue