problems with weak_ptr to python object
Hello, I am working on a project that uses shared_ptr for more or less everything, so weak_ptrs are important. I discovered that the shared_ptrs created by boost.python from python objects that use shared_ptr as a holder are not shared_ptrs managing the same object as the holder, but are shared_ptrs managing a reference to the python object. This is fine until you make a weak_ptr to it. Then the weak_ptr will become invalid way before the actually object is destroyed. See the thread from a year ago called "keeping weak_ptrs upon python objects smart_ptrholders" (http://mail.python.org/pipermail/c++-sig/2003-November/006337.html). There was talk of fixing this problem. Did it go anywhere? I have had the following thoughts: The problem is that a shared_ptr directly related (sharing a use_count) to the holder is only passed to C++ if the type requested exactly matches the holder (I think). And in other cases, a unrelated (seperate use_count) shared_ptr to the same object is passed. If a shared_ptr<void> was used in place of the void*s in the converter code the shared_ptr-ness could be preserved. It would be silly to use shared_ptr<void> when the target type was a plain pointer so maybe it would be possible to make a duplicate of a part of the "conversion path" that used shared_ptr<void>. This path could be used by shared_ptr_from_python to return shared_ptrs that are related to the shared_ptr that is the holder. Does any of that make sense? I'm having trouble explaining my self. Thanks, -Arthur
Arthur Peters wrote:
Hello,
I am working on a project that uses shared_ptr for more or less everything, so weak_ptrs are important. I discovered that the shared_ptrs created by boost.python from python objects that use shared_ptr as a holder are not shared_ptrs managing the same object as the holder, but are shared_ptrs managing a reference to the python object. This is fine until you make a weak_ptr to it. Then the weak_ptr will become invalid way before the actually object is destroyed.
Interesting. The way to get at the underlying shared_ptr is to convert the Python object to a non-const shared_ptr&. So you could do: template <class T> weak_ptr<T> get_weak_ptr(shared_ptr<T> const& x) { object python_owner(x); shared_ptr<T>& inner_shared_ptr( extract<shared_ptr<T>&>(python_owner)); return inner_shared_ptr; // convert to weak_ptr. };
See the thread from a year ago called "keeping weak_ptrs upon python objects smart_ptrholders" (http://mail.python.org/pipermail/c++-sig/2003-November/006337.html). There was talk of fixing this problem. Did it go anywhere?
Was a solution proposed? Oh, I see: ----schnipp------ wouldn't it be possible, when converting the arguments provided to a function, that if : - a shared_ptr (weak_ptr) argument is the 'target' of a specified implicit conversion whose source is the type of the provided value for the argument - AND the provided value wrapper is held by shared_ptr - THEN the shared_ptr " conjured up 'from thin air' " is contructed from the shared_ptr holding the provided value thus having a valid reference count I don't if/where/how all this could be done, and if it covers every aspect of the problem ! -----schnapp------ The problem is that the existing conversion has great value even when the inner objects are held by shared_ptr. If you're going to pass the shared_ptr back to Python you should see the same managing object. Otherwise you can end up with two different Python objects managing the same C++ base sub-object <shiver>.
I have had the following thoughts:
The problem is that a shared_ptr directly related (sharing a use_count) to the holder
You lost me. Which holder?
is only passed to C++ if the type requested exactly matches the holder (I think).
Example?
And in other cases, a unrelated (seperate use_count) shared_ptr to the same object is passed.
If a shared_ptr<void> was used in place of the void*s in the converter code the shared_ptr-ness could be preserved. It would be silly to use shared_ptr<void> when the target type was a plain pointer so maybe it would be possible to make a duplicate of a part of the "conversion path" that used shared_ptr<void>. This path could be used by shared_ptr_from_python to return shared_ptrs that are related to the shared_ptr that is the holder.
Does any of that make sense? I'm having trouble explaining my self.
No and yes ;-) Give some code examples to show what you mean. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com
participants (2)
-
Arthur Peters -
David Abrahams