﻿<html>
<head>
    <title>Improving shared_ptr for C++0x, Revision 1</title>
    <meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema" />
    <meta http-equiv="Content-Language" content="en-us" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body bgcolor="#ffffff">
    <address>
        Document number: N2297=07-0157</address>
    <address>
        Programming Language C++, Library Subgroup</address>
    <address>
        &nbsp;</address>
    <address>
        Peter Dimov, &lt;<a href="mailto:pdimov@pdimov.com">pdimov@pdimov.com</a>&gt;</address>
    <address>
        Beman Dawes, &lt;<a href="mailto:bdawes@acm.org">bdawes@acm.org</a>&gt;</address>
    <address>
        &nbsp;</address>
    <address>
        2007-06-21</address>
    <h1>
        Improving shared_ptr for C++0x, Revision 1</h1>
    <ul>
        <li><a href="#overview">Overview</a></li>
        <li><a href="#allocator">Allocator Support</a></li>
        <li><a href="#aliasing">Aliasing Support</a></li>
        <li><a href="#creation">Object Creation</a></li>
        <li><a href="#move">Move Support</a></li>
        <li><a href="#atomic">Atomic Access</a></li>
        <li><a href="#cycles">Cycle Collection</a></li>
    </ul>
    <h2>
        Changes in Revision 1</h2>
    <ul>
        <li>Expanded the Allocator Support section with more rationale.</li>
        <li>Clarified that the proposed changes are source- and binary-compatible.</li>
        <li>Added rationale for the <code>make_shared</code> name.</li>
        <li>Changed the <code>make_shared</code> proposed wording to use variadic templates
            and changed the Throws clause to reflect the semantics. Remarks added.</li></ul>
    <h2>
        <a name="overview">I. Overview</a></h2>
    <p>
        While <code>shared_ptr</code> has already proven its utility time and again, we
        have observed frequent requests for enhancements in several legitimate and key areas:</p>
    <ul>
        <li>Ability to control its internal allocations;</li>
        <li>Aliasing support;</li>
        <li>A factory function that eliminates the need for an explicit <code>new</code> expression;</li>
        <li>Reduced reference counting overhead when using <code>shared_ptr</code> in "mostly
            unique" ownership situations such as containers;</li>
        <li>A variant of <code>shared_ptr</code> that is <em>atomic</em>, that is, safe to be
            manipulated from multiple threads without synchronization; </li>
        <li>A way to reclaim cyclic <code>shared_ptr</code> structures; </li>
        <li>A variant of <code>shared_ptr</code> that is confined to a single thread and uses
            unsynchronized reference count updates. </li>
    </ul>
    <p>
        This document proposes additions to the C++0x standard to address the first six.
        Some of the proposed additions are essentially a subset of those presented in <a
            href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1851.pdf">N1851</a>
        by Kliatchko and Rocha. We refer the interested reader to that paper for a more
        extensive rationale.</p>
    <p>
        This proposal makes use of variadic templates and rvalue references. These C++0x
        features markedly improve the usability and effectiveness of several of the proposed
        additions.</p>
    <h2>
        <a name="allocator">II. Allocator Support</a></h2>
    <p>
        The default behavior of <code>shared_ptr</code> is to allocate its control block
        using <code>new</code>. This precludes its use in contexts where uncontrolled dynamic
        allocations are not allowed. The proposed addition allows the user to supply an
        allocator that <code>shared_ptr</code> will use.</p>
    <p>
        Boost users have repeatedly been asking for the ability to control the internal
        control block allocation; one particularly amusing occurence was the desire to use
        a <code>shared_ptr</code> in the implementation of <code>::operator new</code>. Typical environments
        where <code>shared_ptr</code> cannot be used as-is include embedded systems and
        computer and video games. Paul Pedriana (one of the primary authors of the Electronic
        Arts STL implementation) writes in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html">
            N2271</a> that</p>
    <blockquote>
        EASTL's shared_ptr/weak_ptr allow the user to specify an allocator instead of implicitly
        using global new</blockquote>
    <p>
        and explains that</p>
    <blockquote>
        As described in the <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html#game_software_issues">
            game software issues</a> section, global new usage is often verboten in game
        software development, at least for console platforms. Thus any library facility
        which uses global operator new or any memory allocation that cannot be controlled
        by the user is unacceptable.</blockquote>
    <p>
        Asked to comment on the proposed addition, Paul kindly offered the following quote:</p>
    <blockquote>
        Certainly we (I can speak for all of Electronic Arts here) are in support of your
        proposal and you can document it as such. You could probably get other game developers
        and embedded developers to agree as well.
    </blockquote>
    <p>
        Vladimir Kliatchko and Ilougino Rocha offer additional arguments in favor of this
        functionality in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1851.pdf">
            N1851</a>, complete with proposed wording. The suggested changes in this paper
        are a subset of those.</p>
    <p>
        The key part of this proposal is that <strong>the allocator is not made part of <code>
            shared_ptr</code>'s type</strong>. It is instead supplied as a parameter to
        the <code>shared_ptr</code> constructor in the same manner as the deleter is. This
        is made possible by the already existing deleter support infrastructure. Coupled
        with the fact that <code>shared_ptr</code> only allocates memory once in its constructor,
        and only deallocates it when the last instance in an ownership group is destroyed,
        this allows us to avoid all common sources of allocator problems. The allocator
        used for the creation of a particular <code>shared_ptr</code> instance remains purely
        an implementation detail for the user of that <code>shared_ptr</code>.</p>
    <p>
        Why use the <code>std::allocator</code> interface if it's widely perceived as "broken"?
        The simple answer is that it works for our (and our users') purposes and is already
        in the Standard.</p>
    <p>
        [Acknowledgments: this allocator interface has been independently suggested by Doug
        Gregor, Joe Gottman, Greg Colvin and others on the Boost list, as well as in N1851.]</p>
    <h3>
        Impact:</h3>
    <p>
        This feature extends the interface of <code>shared_ptr</code> in a backward-compatible
        way, allowing its broader use, and is therefore strongly recommended to be added
        to the C++0x standard. It does not impact existing uses, nor does it introduce binary
        compatibility issues.</p>
    <h3>
        Proposed text:</h3>
    <p>
        Add to <code>shared_ptr</code> [util.smartptr.shared] the following constructor:</p>
    <blockquote>
        <pre>template&lt;class Y, class D, class A&gt; shared_ptr( Y * p, D d, A a );</pre>
    </blockquote>
    <p>
        and the following member function:</p>
    <blockquote>
        <pre>template&lt;class Y, class D, class A&gt; void reset( Y * p, D d, A a );</pre>
    </blockquote>
    <p>
        Change the section:</p>
    <blockquote>
        <pre>template&lt;class Y, class D&gt; shared_ptr( Y * p, D d );</pre>
        <p>
            <em>Requires:</em> <code>p</code> shall be convertible to <code>T*</code>. <code>D</code>
            shall be <code>CopyConstructible</code>. The copy constructor and destructor of
            <code>D</code> shall not throw exceptions. The expression <code>d(p)</code> shall
            be well-formed, shall have well defined behavior, and shall not throw exceptions.</p>
        <p>
            <em>Effects:</em> Constructs a <code>shared_ptr</code> object that <em>owns</em>
            the pointer <code>p</code> and the deleter <code>d</code>.</p>
    </blockquote>
    <p>
        in [util.smartptr.shared.const] to:</p>
    <blockquote>
        <pre>template&lt;class Y, class D&gt; shared_ptr( Y * p, D d );
template&lt;class Y, class D, class A&gt; shared_ptr( Y * p, D d, A a );</pre>
        <p>
            <em>Requires:</em> <code>p</code> shall be convertible to <code>T*</code>. <code>D</code>
            shall be <code>CopyConstructible</code>. The copy constructor and destructor of
            <code>D</code> shall not throw. The expression <code>d(p)</code> shall be well-formed,
            shall have well defined behavior, and shall not throw. <code>A</code> shall be an
            <em>allocator</em> [allocator.requirements]. The copy constructor and destructor
            of <code>A</code> shall not throw.</p>
        <p>
            <em>Effects:</em> Constructs a <code>shared_ptr</code> object that <em>owns</em>
            the pointer <code>p</code> and the deleter <code>d</code>. The second constructor
            shall use a copy of <code>a</code> to allocate memory for internal use.</p>
    </blockquote>
    <p>
        Add the following to [util.smartptr.shared.mod]:</p>
    <blockquote>
        <pre>template&lt;class Y, class D, class A&gt; void reset( Y * p, D d, A a );</pre>
        <p>
            <em>Effects:</em> Equivalent to <code>shared_ptr( p, d, a ).swap( *this )</code>.</p>
    </blockquote>
    <h3>
        Implementability:</h3>
    <p>
        This feature has been added to <code>boost::shared_ptr</code> and will be part of
        Boost 1.35. See:</p>
    <p>
        <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/boost/shared_ptr.hpp">
            http://boost.cvs.sourceforge.net/*checkout*/boost/boost/boost/shared_ptr.hpp</a><br />
        <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/smart_ptr/test/shared_ptr_alloc2_test.cpp">
            http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/smart_ptr/test/shared_ptr_alloc2_test.cpp</a></p>
    <p>
        for reference.</p>
    <h2>
        <a name="aliasing">III. Aliasing Support</a></h2>
    <p>
        Advanced users often require the ability to create a <code>shared_ptr</code> instance
        <code>p</code> that shares ownership with another (master) <code>shared_ptr</code>
        <code>q</code> but points to an object that is not a base of <code>*q</code>. <code>
            *p</code> may be a member or an element of <code>*q</code>, for example. This
        section proposes an additional constructor that can be used for this purpose.</p>
    <p>
        An interesting side effect of this increase of expressive power is that now the
        <code>*_pointer_cast</code> functions can be implemented in user code. The <code>make_shared</code>
        factory function presented later in this document can also be implemented using
        only the public interface of <code>shared_ptr</code> via the aliasing constructor.</p>
    <h3>
        Impact:</h3>
    <p>
        This feature extends the interface of <code>shared_ptr</code> in a backward-compatible
        way that increases its expressive power and is therefore strongly recommended to
        be added to the C++0x standard. It introduces no source- and binary compatibility
        issues.</p>
    <h3>
        Proposed text:</h3>
    <p>
        Add to <code>shared_ptr</code> [util.smartptr.shared] the following constructor:</p>
    <blockquote>
        <pre>template&lt;class Y&gt; shared_ptr( shared_ptr&lt;Y&gt; const &amp; r, T * p );</pre>
    </blockquote>
    <p>
        Add the following to [util.smartptr.shared.const]:</p>
    <blockquote>
        <pre>template&lt;class Y&gt; shared_ptr( shared_ptr&lt;Y&gt; const &amp; r, T * p );</pre>
        <p>
            <em>Effects:</em> Constructs a <code>shared_ptr</code> instance that stores <code>p</code>
            and <em>shares ownership</em> with <code>r</code>.</p>
        <p>
            <em>Postconditions:</em> <code>get() == p &amp;&amp; use_count() == r.use_count()</code>.</p>
        <p>
            <em>Throws:</em> nothing.</p>
        <p>
            <em>[Note:</em> To avoid the possibility of a dangling pointer, the user of this
            constructor must ensure that <code>p</code> remains valid at least until the ownership
            group of <code>r</code> is destroyed. <em>--end note.]</em></p>
        <p>
            <em>[Note:</em> This constructor allows creation of an <em>empty</em> <code>shared_ptr</code>
            instance with a non-NULL stored pointer. <em>--end note.]</em></p>
    </blockquote>
    <h3>
        Implementability:</h3>
    <p>
        This feature has been added to <code>boost::shared_ptr</code> and will be part of
        Boost 1.35. See:</p>
    <p>
        <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/boost/shared_ptr.hpp">
            http://boost.cvs.sourceforge.net/*checkout*/boost/boost/boost/shared_ptr.hpp</a><br />
        <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/smart_ptr/test/shared_ptr_alias_test.cpp">
            http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/smart_ptr/test/shared_ptr_alias_test.cpp</a></p>
    <p>
        for reference.</p>
    <h2>
        <a name="creation">IV. Object Creation</a></h2>
    <p>
        Consistent use of <code>shared_ptr</code> can eliminate the need to use an explicit
        <code>delete</code>, but it currently provides no support in avoiding explicit <code>
            new</code>. There have been repeated requests from users for a factory function
        that creates an object of a given type and returns a <code>shared_ptr</code> to
        it. Besides convenience and style, such a function is also exception safe and considerably
        faster because it can use a single allocation for the object and its corresponding
        control block, eliminating a significant portion of <code>shared_ptr</code>'s construction
        overhead. This function eliminates one of the major efficiency complaints about
        <code>shared_ptr</code>.</p>
    <p>
        This section proposes a family of overloaded function templates, <code>make_shared&lt;T&gt;</code>
        and <code>allocate_shared&lt;T&gt;</code>, to address this need. <code>make_shared</code>
        uses the global <code>operator new</code> to allocate memory, whereas <code>allocate_shared</code>
        uses an user-supplied allocator, allowing finer control consistent with <a href="#allocator">
            section II</a> of this document.</p>
    <p>
        The rationale for choosing the name <code>make_shared</code> is that the expression
        <code>make_shared&lt;Widget&gt;()</code> can be read aloud and conveys the intended
        meaning. A free function also enables a non-intrusive implementation that can be
        delivered without modifications to an existing <code>shared_ptr</code> implementation.</p>
    <h3>
        Impact:</h3>
    <p>
        This feature does not affect the interface of <code>shared_ptr</code>. It is possible
        to implement in a non-intrusive way using only the public interface, <strong>as long
            as aliasing support is present</strong>. Access to implementation details can
        eliminate between 5 and 8 bytes of storage overhead on a typical 32 bit platform.</p>
    <p>
        The addition is a strong candidate for the C++0x standard, but can be relegated
        to a technical report.</p>
    <h3>
        Proposed text:</h3>
    <h4>
        Synopsis:</h4>
    <blockquote>
        <pre>namespace std {
  template&lt;class T&gt; shared_ptr&lt;T&gt; make_shared();
  template&lt;class T, class A&gt; shared_ptr&lt;T&gt; allocate_shared( A const &amp; a );

  template&lt;class T, class A1, ..., class An&gt; shared_ptr&lt;T&gt; make_shared( A1 const &amp; a1, ..., An const &amp; an );
  template&lt;class T, class A, class A1, ..., class An&gt; shared_ptr&lt;T&gt; allocate_shared( A const &amp; a, A1 const &amp; a1, ..., An const &amp; an );
}
</pre>
    </blockquote>
    <h4>
        Description:</h4>
    <blockquote>
        <pre>template&lt;class T&gt; shared_ptr&lt;T&gt; make_shared();
template&lt;class T, class A&gt; shared_ptr&lt;T&gt; allocate_shared( A const &amp; a );

template&lt;class T, class... Args&gt; shared_ptr&lt;T&gt; make_shared( Args &amp;&amp; ... args );
template&lt;class T, class... Args&gt; shared_ptr&lt;T&gt; allocate_shared( A const &amp; a, Args &amp;&amp; ... args );
</pre>
        <p>
            <em>Requires:</em> The expression <code>new( pv ) T()</code> or <code>new( pv ) T( std::forward&lt;Args&gt;(args)...
                )</code>, where <code>pv</code> is a <code>void*</code> pointing to storage
            suitable to hold an object of type <code>T</code>, shall be well-formed and shall
            have well defined behavior. <code>A</code> shall be an <em>allocator</em> [allocator.requirements].
            The copy constructor and destructor of <code>A</code> shall not throw.</p>
        <p>
            <em>Effects:</em> Allocates memory suitable for an object of type <code>T</code>
            and constructs an object in it via the placement new expression <code>new( pv ) T()</code>
            or <code>new( pv ) T( std::forward&lt;Args&gt;(args)... )</code>.
            <code>allocate_shared</code> uses a copy of <code>a</code> to allocate memory.</p>
        <p>
            <em>Returns:</em> A <code>shared_ptr</code> instance that stores and owns the address
            of the newly constructed object of type <code>T</code>.</p>
        <p>
            <em>Postconditions:</em> <code>get() != 0 &amp;&amp; use_count() == 1</code>.</p>
        <p>
            <em>Throws:</em> <code>bad_alloc</code>, or an exception thrown from <code>A::allocate</code>
            or the constructor of <code>T</code>.</p>
        <p>
            <em>Exception safety:</em> If an exception is thrown, has no effect.</p>
        <p>
            <em>Remarks:</em> Implementations are encouraged, but not required, to perform no more than one memory allocation. <em>[Note:</em> This provides efficiency equivalent to an intrusive smart pointer. <em>--end note]</em></p>
        <p>
            <em>[Note:</em> These functions will typically allocate more memory than <code>sizeof(T)</code>
            to allow for internal bookkeeping structures such as the reference counts. <em>--end
                note]</em></p>
    </blockquote>
    <h3>
        Implementability:</h3>
    <p>
        A proof of concept non-intrusive implementation is available at:</p>
    <p>
        <a href="http://www.pdimov.com/cpp/make_shared.cpp">http://www.pdimov.com/cpp/make_shared.cpp</a></p>
    <p>
        This implementation uses variadic templates and rvalue references. When these features
        are not available, it falls back on a family of overloaded function templates taking
        arguments by const reference.</p>
    <h2>
        <a name="move">V. Move Support</a></h2>
    <p>
        Users often express concerns over the cost of copying a <code>shared_ptr</code>
        in situations where the source of the copy is no longer needed. To address this
        use case, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1851.pdf">
            N1851</a> proposes a separate smart pointer, <code>managed_ptr</code>, that
        is convertible from and to <code>shared_ptr</code> and enforces unique ownership.</p>
    <p>
        The current proposal does not take this approach. Instead, we propose that move
        constructors and move assignment operators be added to <code>shared_ptr</code>.
        This allows a <code>shared_ptr</code> to be as efficient as an <code>auto_ptr</code>
        or the proposed <code>unique_ptr</code> when the source of the copy or assignment
        is a temporary or no longer needed. Move-aware standard containers will automatically
        take advantage of this optimization. As an example of the consequences, reallocating
        a <code>vector&lt; shared_ptr&lt;T&gt; &gt;</code> will no longer entail any reference
        count updates.</p>
    <h3>
        Impact:</h3>
    <p>
        This feature affects the interface of <code>shared_ptr</code> in a way that reduces
        its copy overhead and is in line with the rvalue recommendations for the standard
        library presented in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1856.html">
            N1859</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1862.html">N1862</a>.
        We believe that it is a strong candidate for addition to the C++0x standard.</p>
    <h3>
        Proposed text:</h3>
    <p>
        Add to <code>shared_ptr</code> [util.smartptr.shared] the following:</p>
    <blockquote>
        <pre>shared_ptr( shared_ptr &amp;&amp; r );
template&lt;class Y&gt; shared_ptr( shared_ptr&lt;Y&gt; &amp;&amp; r );

shared_ptr&amp; operator=( shared_ptr &amp;&amp; r );
template&lt;class Y&gt; shared_ptr&amp; operator=( shared_ptr&lt;Y&gt; &amp;&amp; r );
</pre>
    </blockquote>
    <p>
        Add the following to [util.smartptr.shared.const]:</p>
    <blockquote>
        <pre>shared_ptr( shared_ptr &amp;&amp; r );
template&lt;class Y&gt; shared_ptr( shared_ptr&lt;Y&gt; &amp;&amp; r );</pre>
        <p>
            <em>Requires:</em> For the second constructor <code>Y*</code> shall be convertible
            to <code>T*</code>.</p>
        <p>
            <em>Effects:</em> Move-constructs a <code>shared_ptr</code> instance from <code>r</code>.</p>
        <p>
            <em>Postconditions:</em> <code>*this</code> contains the old value of <code>r</code>.
            <code>r</code> is <em>empty</em>.</p>
        <p>
            <em>Throws:</em> nothing.</p>
    </blockquote>
    <p>
        Add the following to [util.smartptr.shared.assign]:</p>
    <blockquote>
        <pre>shared_ptr&amp; operator=( shared_ptr &amp;&amp; r );
template&lt;class Y&gt; shared_ptr&amp; operator=( shared_ptr&lt;Y&gt; &amp;&amp; r );</pre>
        <p>
            <em>Effects:</em> Equivalent to <code>shared_ptr( move( r ) ).swap( *this )</code>.</p>
        <p>
            <em>Returns:</em> <code>*this</code>.</p>
    </blockquote>
    <h3>
        Implementability:</h3>
    <p>
        This feature has been added to <code>boost::shared_ptr</code> and will be part of
        Boost 1.35.</p>
    <h2>
        <a name="atomic">VI. Atomic Access</a></h2>
    <p>
        The level of thread safety offered by <code>shared_ptr</code> is the default for
        the standard library: const operations on the same instance can be performed concurrently
        by multiple threads, but updates require exclusive access. Some scenarios require
        stronger guarantees; there is considerable demand (on the Boost mailing lists and
        otherwise) for an <em>atomic</em> <code>shared_ptr</code>, one that can withstand
        concurrent updates from two threads without synchronization.</p>
    <p>
        Instead of providing a separate atomic smart pointer, we propose additions to <code>
            shared_ptr</code>'s interface to address this use case. A typical example scenario
        &mdash; a "lock-free" reader/writer pattern &mdash; that takes advantage of this
        functionality is outlined below:</p>
    <pre>shared_ptr&lt;State&gt; ps;

void reader()
{
    shared_ptr&lt;State&gt; p = ps.copy();
    <em>use *p;</em>
}

// single writer case
void writer()
{
    shared_ptr&lt;State&gt; p( new State( *ps ) );
    <em>update *p reflecting new information;</em>
    ps.replace( move( p ) );
}

// or, multiple writers case
void writer()
{
    shared_ptr&lt;State&gt; p = ps.copy();
    do
    {
        shared_ptr&lt;State&gt; q( new State( *p ) );
        <em>update *q reflecting new information;</em>
    }
    while( !ps.compare_swap( p, move( q ) ) );
}
</pre>
    <h3>
        Impact:</h3>
    <p>
        This feature extends the interface of <code>shared_ptr</code> in a backward-compatible
        way. We believe that it is a strong candidate for addition to the C++0x standard.
        It introduces no source- or binary compatibility issues.</p>
    <h3>
        Proposed text:</h3>
    <p>
        Add to <code>shared_ptr</code> [util.smartptr.shared] the following:</p>
    <blockquote>
        <pre>// <em>[util.smartptr.shared.atomic], atomic access:</em>

shared_ptr copy() const;
void replace( shared_ptr r );
bool compare_swap( shared_ptr &amp; v, shared_ptr w );
</pre>
    </blockquote>
    <p>
        Add a new section [util.smartptr.shared.atomic]:</p>
    <blockquote>
        <p>
            A program is allowed to access the same <code>shared_ptr</code> instance concurrently
            from multiple threads if the access is done exclusively via the member functions
            in this section.</p>
        <pre>shared_ptr copy() const;</pre>
        <p>
            <em>Returns:</em> <code>*this</code>.</p>
        <p>
            <em>Throws:</em> nothing.</p>
        <pre>void replace( shared_ptr r );</pre>
        <p>
            <em>Effects:</em> <code>swap( r )</code>.</p>
        <p>
            <em>Throws:</em> nothing.</p>
        <pre>bool compare_swap( shared_ptr &amp; v, shared_ptr w );</pre>
        <p>
            <em>Effects:</em> If <code>*this</code> is equivalent to <code>v</code>, assigns
            <code>w</code> to <code>*this</code>, otherwise assigns <code>*this</code> to <code>
                v</code>.</p>
        <p>
            <em>Returns:</em> <code>true</code> if <code>*this</code> was equivalent to <code>v</code>,
            <code>false</code> otherwise.</p>
        <p>
            <em>Throws:</em> nothing.</p>
        <p>
            <em>Remarks:</em> two <code>shared_ptr</code> instances are equivalent if they store
            the same pointer value and <em>share ownership</em>.</p>
    </blockquote>
    <h3>
        Implementability:</h3>
    <p>
        A typical implementation would use a spinlock pool as described in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2145.html">
            N2145</a>. In pseudocode, the functions will be implemented as follows:</p>
    <blockquote>
        <pre>shared_ptr copy() const
{
    <em>lock the spinlock for *this</em>;
    shared_ptr r( *this );
    <em>unlock the spinlock for *this</em>;
    return r;
}

void replace( shared_ptr r )
{
    <em>lock the spinlock for *this</em>;
    swap( r );
    <em>unlock the spinlock for *this</em>;
}

bool compare_swap( shared_ptr &amp; v, shared_ptr w )
{
    <em>lock the spinlock for *this</em>;

    if( <em>*this is equivalent to v</em> )
    {
        swap( w );
        <em>unlock the spinlock for *this</em>;
        return true;
    }
    else
    {
        shared_ptr tmp( *this );
        <em>unlock the spinlock for *this</em>;
        tmp.swap( v );
        return false;
    }
}
</pre>
    </blockquote>
    <p>
        Note that the code carefully avoids destroying a non-empty <code>shared_ptr</code>
        instance while holding the spinlock, as this may lead to user code being called
        and present an opportunity for a deadlock. It also attempts to limit the spinlock
        scope to the minimum necessary to prevent contention.</p>
    <h2>
        <a name="cycles">VII. Cycle Collection</a></h2>
    <p>
        The inability of <code>shared_ptr</code> to handle cyclic structures has long been
        cited as one of its important downsides. The proposed addition offers a way for
        users to opt to reclaim cyclic structures via implementing a support interface for
        their nodes. It imposes no overhead on existing non-cyclic uses that do not implement
        the interface.</p>
    <h3>
        Impact:</h3>
    <p>
        This feature does not affect the interface of <code>shared_ptr</code>, but requires
        support from the implementation in a similar way to <code>enable_shared_from_this</code>.
        We believe that it is therefore a candidate for addition to the C++0x standard.</p>
    <h3>
        Proposed text:</h3>
    <p>
        Add to the synopsis of <code>&lt;memory&gt;</code> the following:</p>
    <blockquote>
        <pre>class enable_sp_collect;
void sp_collect();</pre>
    </blockquote>
    <p>
        Add the following two sections after [util.smartptr.enab]:</p>
    <blockquote>
        <h4>
            Class enable_sp_collect</h4>
        <p>
            A class that derives from <code>enable_sp_collect</code> via public and unambiguous
            inheritance is called <em>collectible</em>. The implementation tracks all collectible
            classes owned by <code>shared_ptr</code> instances and can reclaim cycles of unreachable
            collectible objects.</p>
        <pre>namespace std {

  class enable_sp_collect
  {
  protected:
    ~enable_sp_collect() {}
  public:
    virtual void sp_enumerate( vector&lt; shared_ptr&lt;enable_sp_collect&gt; &gt; &amp; v ) = 0;
    virtual void sp_reset() = 0;
  };

} // namespace std
</pre>
        <pre>virtual void sp_enumerate( vector&lt; shared_ptr&lt;enable_sp_collect&gt; &gt; &amp; v ) = 0;</pre>
        <p>
            <em>Effects:</em> Appends all <code>shared_ptr</code> instances to <em>collectible</em>
            objects that <code>*this</code> owns to <code>v</code>.</p>
        <pre>virtual void sp_reset() = 0;</pre>
        <p>
            <em>Effects:</em> Resets or destroys all <code>shared_ptr</code> instances to <em>collectible</em>
            objects that <code>*this</code> owns.</p>
        <p>
            <em>Throws:</em> nothing.</p>
        <p>
            <em>[Note:</em> This function may be called while the collector is holding a lock.
            Performing anything else besides resetting the <code>shared_ptr</code> instances
            is strongly discouraged as it may lead to deadlocks. <em>--end note]</em></p>
        <p>
            <em>[Example:</em></p>
        <pre>class Node: public enable_sp_collect
{
private:

  shared_ptr&lt;Node&gt; link;
  vector&lt; shared_ptr&lt;Node&gt; &gt; links;

public:

  void sp_enumerate( vector&lt; shared_ptr&lt;enable_sp_collect&gt; &gt; &amp; v )
  {
    v.push_back( link );
    v.insert( v.end(), links.begin(), links.end() );
  }

  void sp_reset()
  {
    link.reset();
    links.clear();
  }
};
</pre>
        <p>
            <em>--end example]</em></p>
        <h4>
            sp_collect</h4>
        <pre>namespace std {

  void sp_collect();

}</pre>
        <p>
            <em>Effects:</em> For every collectible object owned by a <code>shared_ptr</code>,
            calls <code>sp_enumerate</code>. Performs reachability analysis on the returned
            data and identifies the unreachable collectible objects. Retains temporary <code>shared_ptr</code>
            references to all unreachable objects. For every unreachable object, calls <code>sp_reset</code>.
            Drops the temporary references, causing the destruction of the unreachable objects.</p>
        <p>
            <em>[Note:</em> This function is allowed to be called in a separate thread. <em>--end
                note]</em></p>
        <p>
            <em>[Note:</em> The reachability analysis may be performed using Christopher's algorithm.
            Using the instance graph, compute the use counts the objects would have if there
            were no external <code>shared_ptr</code> instances. Compare the computed use counts
            with the actual use counts. For every mismatch, mark the object as reachable from
            the outside. Propagate reachability throughout the graph. <em>--end note]</em></p>
    </blockquote>
    <h3>
        Implementability:</h3>
    <p>
        A very preliminary proof of concept implementation is available at:</p>
    <p>
        <a href="http://www.pdimov.com/cpp/enable_sp_collect.cpp">http://www.pdimov.com/cpp/enable_sp_collect.cpp</a></p>
    <p>
        It is expected to be integrated with <code>boost::shared_ptr</code> in time for
        the mailing.</p>
    <hr />
    <p>
        <em>Thanks to Joe Gottman for his comments on the move support.</em></p>
    <p>
        <em>Thanks to Jens Maurer for his comments on the <code>make_shared</code> wording.</em></p>
    <p>
        <em>--end</em></p>
</body>
</html>
