[C++-sig] alternative smart pointer (intrusive_ptr) example

Jeff Webb jeff.webb at nta-inc.net
Thu Jul 24 22:23:10 CEST 2008


The boost::python library provides excellent support for wrapping C++ objects managed by boost::shared_ptr reference counting smart pointers.  I am attempting to achieve similar functionality with a little less memory overhead by embedding the reference count in the managed object and using boost::intrusive_ptr instead.

I have come up with an implementation that I would like to post to this list for two reasons.  First of all, I would be thrilled if some more knowledgeable folks would look over the code and let me know if my approach is flawed in some way.  Secondly, I think the principles I am discussing will be of interest to others on the list, and possibly the code itself.

Instead of posting the whole implementation at once, I am going to start out with something very basic.  I will then point out some deficiencies and address them one at a time, modifying the code to overcome each one.  I think this approach will be more understandable than throwing the whole mess of code out there at once.

The attached mod1.cpp file defines a base class for reference counted objects (called "Pointee") and provides the functions required for managing Pointee objects with intrusive_ptr.  The module also defines two test classes that are exposed to python.  The VerbosePointee class is just a subclass of Pointee that contains print statements for illustration purposes.  RefHolder is a subclass of VerbosePointee that contains a member called 'ref', which is an intrusive_ptr that can reference another VerbosePointee object.

Here is a sample python session using this module:


>>> from mod1 import *

>>> r = RefHolder()
creating 0x1d544af0

>>> print r.ref
None

>>> v = VerbosePointee()
creating 0x1d6b6190

>>> r.ref = v

>>> print r.ref
<mod1.VerbosePointee object at 0x1df70590>

>>> r.ref is v
False

>>> r.ref.id == v.id
True

>>> del v

>>> del r
destroying 0x1d6b6190
destroying 0x1d544af0

>>> r1 = RefHolder()
creating 0x1de86a80

>>> r2 = RefHolder()
creating 0x1d544bf0

>>> r1.ref = r2
--------------------------
Boost.Python.ArgumentError

ArgumentError: Python argument types in 
    None.None(RefHolder, RefHolder)
did not match C++ signature:
    None(RefHolder {lvalue}, boost::intrusive_ptr<VerbosePointee>)

>>> r1.ref = None
---------------------------------------------------------------------------
Boost.Python.ArgumentError

ArgumentError: Python argument types in
    None.None(RefHolder, NoneType)
did not match C++ signature:
    None(RefHolder {lvalue}, boost::intrusive_ptr<VerbosePointee>)


The memory management works as one would expect, but a few deficiencies are evident in the session shown above:

(1) There is an object identity problem (i.e. 'r.ref is v' is False).  This means that there are two python wrappers for a single C++ object.  In some cases this is okay, but it is not ideal.

(2) RefHolder objects cannot hold a reference to another RefHolder object, even though RefHolder is a subclass of VerbosePointee.

(3) Although a null pointer is translated to python as None, a RefHolder's ref member cannot be assigned a value of None.

In future posts, I will post my proposed solution to the problems mentioned above and address other issues as they arise.

Any comments/questions so far?

-Jeff
-------------- next part --------------
A non-text attachment was scrubbed...
Name: mod1.cpp
Type: text/x-c++src
Size: 2816 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20080724/7e3d6e0e/attachment.cpp>


More information about the Cplusplus-sig mailing list