Properly transferring ownership for variant to Python/Ruby translation

This commit is contained in:
Matthias Koefferlein 2024-07-25 21:07:36 +02:00
parent 58d489b39a
commit a0d26a59e3
6 changed files with 53 additions and 4 deletions

View File

@ -533,8 +533,13 @@ PyObject *c2python_func<const tl::Variant &>::operator() (const tl::Variant &c)
const gsi::ClassBase *cls = c.gsi_cls ();
if (cls) {
void *obj = const_cast<void *> (c.to_user ());
return object_to_python (obj, 0, c.user_cls ()->gsi_cls (), false, false, true, false);
if (! c.user_is_ref () && cls->is_managed ()) {
void *obj = c.user_unshare ();
return object_to_python (obj, 0, c.user_cls ()->gsi_cls (), true, c.user_is_const (), false, false);
} else {
void *obj = const_cast<void *> (c.to_user ());
return object_to_python (obj, 0, c.user_cls ()->gsi_cls (), false, false, true, false);
}
} else {
// not a known type -> return nil
Py_RETURN_NONE;

View File

@ -287,8 +287,13 @@ VALUE c2ruby<tl::Variant> (const tl::Variant &c)
} else if (c.is_user ()) {
const gsi::ClassBase *cls = c.gsi_cls ();
if (cls) {
void *obj = const_cast<void *> (c.to_user ());
return object_to_ruby (obj, 0, c.user_cls ()->gsi_cls (), false, false, true, false);
if (! c.user_is_ref () && cls->is_managed ()) {
void *obj = c.user_unshare ();
return object_to_ruby (obj, 0, c.user_cls ()->gsi_cls (), true, c.user_is_const (), false, false);
} else {
void *obj = const_cast<void *> (c.to_user ());
return object_to_ruby (obj, 0, c.user_cls ()->gsi_cls (), false, false, true, false);
}
} else {
// not a known type -> return nil
return Qnil;

View File

@ -227,6 +227,11 @@ const Object *WeakOrSharedPtr::get () const
return mp_t;
}
void WeakOrSharedPtr::unshare ()
{
m_is_shared = false;
}
void WeakOrSharedPtr::reset_object ()
{
tl::MutexLocker locker (&lock ());

View File

@ -197,6 +197,12 @@ public:
*/
void detach_from_all_events ();
/**
* @brief Unshares the object
* This will turn a shared reference into a weak one.
*/
void unshare ();
/**
* @brief Indicates that this object is an event
* This property is intended for internal use only.
@ -401,6 +407,9 @@ public:
{
// .. nothing yet ..
}
private:
using weak_or_shared_ptr<T, false>::unshare;
};
/**
@ -429,6 +438,9 @@ public:
{
// .. nothing yet ..
}
private:
using weak_or_shared_ptr<T, true>::unshare;
};
}

View File

@ -2709,6 +2709,21 @@ void *Variant::user_take ()
return obj;
}
void *Variant::user_unshare () const
{
tl_assert (is_user () && ! user_is_ref ());
if (m_type == t_user) {
Variant *nc_this = const_cast<Variant *> (this);
nc_this->m_var.mp_user.shared = false;
} else if (m_type == t_user_ref) {
tl::WeakOrSharedPtr *wptr = const_cast<tl::WeakOrSharedPtr *> (reinterpret_cast <const tl::WeakOrSharedPtr *> (m_var.mp_user_ref.ptr));
wptr->unshare ();
}
return const_cast<void *> (to_user ());
}
void Variant::user_assign (const tl::Variant &other)
{
tl_assert (is_user ());

View File

@ -891,6 +891,13 @@ public:
*/
void *user_take ();
/**
* @brief Takes the user object and releases ownership by the variant
* This method is const as it does not change the value, but the ownership of
* the contained object. The object must not be "user_is_ref".
*/
void *user_unshare () const;
/**
* @brief Assigns the object stored in other to self
*