[webkit-dev] New smart pointers for efficient refcounting

Maciej Stachowiak mjs at apple.com
Tue Nov 29 20:24:50 PST 2005


Hi everyone,

In many places, to get memory management right, it is way more  
convenient and less error-prone to use a smart pointer, like SharedPtr 
(*). However, sometimes this leads to needless thrashing of the  
refcount. For example, any function that returns a newly created  
refcounted object should really give you a SharedPtr, to avoid  
leaking. But suppose that value is going to go directly into a data  
member that is a SharedPtr. That's going to lead to an extra ref and  
deref. In some spots that actually shows up on the profile. With  
manual refcounting you can special-case taking ownership of a newly  
created object, and avoid the extra ref and deref.

I came up with a simple idea for how to deploy smart pointers  
throughout without suffering from this refcount thrash. It is  
inspired by the standard C++ library's auto_ptr.

The basic idea is that you keep SharedPtr for most purposes; but in  
interfaces where you pass ownership, you use the new PassRefPtr.  
Passing ownership means either returning a newly allocated object (or  
otherwise one that the callee won't hold onto), or passing in as an  
argument an object the function is guaranteed to ref and hold onto.

PassRefPtr works just like SharedPtr in most respects, except for  
assignment semantics:

SharedPtr = SharedPtr // both keep a ref
PassRefPtr = SharedPtr // both keep a ref
SharedPtr = PassRefPtr // PassRefPtr transfers ownership and nils  
itself out
PassRefPtr = PassRefPtr // second PassRefPtr transfers ownership and  
nils itself out


Then you follow these rules:

- local variables, global variables and data members should be a  
SharedPtr if they maintain a referece, or a raw pointer if they don't  
need to (for example a parent pointer, where the parent owns you)

- function return values and parameters should be a raw pointer or a  
PassRefPtr (not a PassRefPtr& or const PassRefPtr&), depending on  
whether they transfer ownership

- sometimes you might want to use a PassRefPtr for a local variable,  
if you plan to immediately transfer ownership

Here's a test program I made that includes the PassRefPtr  
implementation and demonstrates use. A function getRefCounter returns  
a PassRefPtr which is then passed off to an Acceptor object's  
constructor.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: reftest.cpp
Type: application/octet-stream
Size: 6559 bytes
Desc: not available
Url : http://lists.macosforge.org/pipermail/webkit-dev/attachments/20051129/cf32156d/reftest.obj
-------------- next part --------------

This runs in 2.95 seconds compared to 3.05 for this naiive SharedPtr  
version:

-------------- next part --------------
A non-text attachment was scrubbed...
Name: reftest2.cpp
Type: application/octet-stream
Size: 6556 bytes
Desc: not available
Url : http://lists.macosforge.org/pipermail/webkit-dev/attachments/20051129/cf32156d/reftest2.obj
-------------- next part --------------

So it's a measurable speedup to save those extra refs and derefs at  
construction time.

I plan to integrate this soon. Any thoughts?

Regards,
Maciej


* - I'd also like to rename SharedPtr to RefPtr and Shared to  
RefCounted, but I'm gonna stick with the SharedPtr terminology for  
this email.


More information about the webkit-dev mailing list