microsoft/xlang

python: persisting Python object when passing to WinRT APIs

dlech opened this issue · 1 comments

dlech commented

Currently, a new Python object is created each time a WinRT (COM) object is passed from a WinRT API to Python. For example in the case of events, each time an event delegate is called, new Python objects are created for the sender object. I suspect from experience that for frequently called events, this has a measurable performance impact.

It looks like there used to be some sort of table to cache objects:

// TODO: re-enable instance wrapper caching
// if obj is null, remove from instance_map
//if (obj)
//{
// auto insert = instance_map.try_emplace(key, obj);
// if (insert.second == false)
// {
// throw winrt::hresult_invalid_argument(L"wrapped WinRT object already cached");
// }
//}
//else
//{
// // TODO: clean up the wrapped WinRT object. Currently leaking
// instance_map.extract(key);
//}

But I suspect that this was disabled because you can't really do something like this without leaking references (as noted in the comment in the code).

To not leak, we need something like toggle references in GObject.

This functionality is intended for binding object to a proxy object managed by another memory manager. This is done with two paired references: the strong reference added by g_object_add_toggle_ref() and a reverse reference to the proxy object which is either a strong reference or weak reference.

The setup is that when there are no other references to object , only a weak reference is held in the reverse direction from object to the proxy object, but when there are other references held to object , a strong reference is held. The notify callback is called when the reference from object to the proxy object should be "toggled" from strong to weak (is_last_ref true) or weak to strong (is_last_ref false).

Since a (normal) reference must be held to the object before calling g_object_add_toggle_ref(), the initial state of the reverse link is always strong.

Multiple toggle references may be added to the same gobject, however if there are multiple toggle references to an object, none of them will ever be notified until all but one are removed. For this reason, you should only ever use a toggle reference if there is important state in the proxy object.

I am wondering if the deferred destruction/final_release feature of cppwinrt could be used for this. Is this feature available on all objects? Is it possible to "resurrect" an object in the final_release function (e.g. increase the ref count and keep using the object instead of destroying it)?

Is there a way to attach arbitrary data to a COM object or is a hash table the best we can do?

This issue is stale because it has been open 10 days with no activity. Remove stale label or comment or this will be closed in 5 days.