C++: put the parent in a weak pointer

Right now we always `lock().value()` it which is the equivalent of
`upgrade().unwrap()` in rust, this helps because it keeps the parent
alive when we are calling function in it.

Ideally we should also check that it wasn't deleted, but that's another
issue.

Fixes #7880
This commit is contained in:
Olivier Goffart 2025-03-28 13:11:35 +01:00
parent ad5d769aee
commit aca30901be
3 changed files with 83 additions and 22 deletions

View file

@ -195,4 +195,50 @@ public:
const VTable *vtable() const { return inner ? inner->vtable : nullptr; }
};
template<typename VTable, typename MappedType>
class VRcMapped
{
VRc<VTable, Dyn> parent_strong;
MappedType *object;
template<typename VTable_, typename MappedType_>
friend class VWeakMapped;
public:
/// Constructs a pointer to MappedType that shares ownership with parent_strong.
template<typename X>
explicit VRcMapped(VRc<VTable, X> parent_strong, MappedType *object)
: parent_strong(parent_strong.into_dyn()), object(object)
{
}
const MappedType *operator->() const { return object; }
const MappedType &operator*() const { return *object; }
MappedType *operator->() { return object; }
MappedType &operator*() { return *object; }
};
template<typename VTable, typename MappedType>
class VWeakMapped
{
VWeak<VTable, Dyn> parent_weak;
MappedType *object = nullptr;
public:
VWeakMapped(const VRcMapped<VTable, MappedType> &strong)
: parent_weak(strong.parent_strong), object(strong.object)
{
}
VWeakMapped() = default;
std::optional<VRcMapped<VTable, MappedType>> lock() const
{
if (auto parent = parent_weak.lock()) {
return VRcMapped<VTable, MappedType>(std::move(*parent), object);
} else {
return {};
}
}
};
} // namespace vtable